标签:
链接:http://www.cnblogs.com/jackge/archive/2013/04/20/3032942.html
题意:给定一字符串,求它所有的前缀出现的次数的和。
这题很纠结,一开始不知道怎么做,如果直接统计子串在主串中出现的次数,orz···肯定
TLE,后来发现这题可以直接从next数组入手,因为next数组表示的是子串中最长公共前后缀串的长度,如果用dt[i]表示该字符串前i个字符中出
现任意以第i个字符结尾的前缀的次数,它的递推式是
dt[i]=d[next[i]]+1,即以第i个字符结尾的前缀数等于以第next[i]个字符为结尾的前缀数加上它自己本身,这里要好好理解一下,不
太好解释。
举个例子:
i 1 2 3 4 5 6
字符串 a b a b a b
dt[i] 1 1 2 2 3 3
aba中出现的前缀为a,aba,所以dt[3]是2,ababa中出现的前缀为a,aba,ababa,所以dt[5]是3,当i=5时,next[5]=3,所以dt[i]=dt[next[i]]+1
理解了上面的部分就很简单了,后面直接套next数组的模板
#include <bits/stdc++.h> using namespace std; const int INF=0x3f3f3f3f; typedef long long LL; #define PI(A) printf("%d\n",A) #define SI(N) scanf("%d",&(N)) #define SII(N,M) scanf("%d%d",&(N),&(M)) #define cle(a,val) memset(a,(val),sizeof(a)) #define rep(i,b) for(int i=0;i<(b);i++) #define Rep(i,a,b) for(int i=(a);i<=(b);i++) #define reRep(i,a,b) for(int i=(a);i>=(b);i--) const double EPS= 1e-9 ; /* ///////////////////////// C o d i n g S p a c e ///////////////////////// */ const int MAXN= 200000 + 5 ; //kuangbin 模板 void kmp_pre(char x[],int m,int Next[]) { int i,j; j=Next[0]=-1; i=0; while(i<m) { while(-1!=j&&x[i]!=x[j]) j=Next[j]; Next[++i]=++j; } } char str[MAXN]; int Next[MAXN]; int dp[MAXN]; int M=10007; int main() { int o; SI(o); while(o--) { int n; SI(n); scanf("%s",str); kmp_pre(str,n,Next); int ans=0; Rep(i,1,n) { dp[i]=dp[Next[i]]+1; ans=(ans+dp[i])%M; } PI(ans); } return 0; }
以下是next测试函数,可以自己测一下,有助于理解next原理
随便输入字符串,最后输出字符串,和对应next的值,
#include <bits/stdc++.h> using namespace std; const int INF=0x3f3f3f3f; typedef long long LL; #define PI(A) printf("%d\n",A) #define SI(N) scanf("%d",&(N)) #define SII(N,M) scanf("%d%d",&(N),&(M)) #define cle(a,val) memset(a,(val),sizeof(a)) #define rep(i,b) for(int i=0;i<(b);i++) #define Rep(i,a,b) for(int i=(a);i<=(b);i++) #define reRep(i,a,b) for(int i=(a);i>=(b);i--) const double EPS= 1e-9 ; /* ///////////////////////// C o d i n g S p a c e ///////////////////////// */ const int MAXN= 200000 + 5 ; //kuangbin 模板 void kmp_pre(char x[],int m,int Next[]) { int i,j; j=Next[0]=-1; i=0; while(i<m) { while(-1!=j&&x[i]!=x[j]) j=Next[j]; Next[++i]=++j; } } char str[MAXN]; int Next[MAXN]; int dp[MAXN]; int M=10007; int main() { while(~scanf("%s",str)) { kmp_pre(str,strlen(str),Next); printf(" "); rep(i,strlen(str)) { printf("%c ",str[i]); }puts(""); rep(i,strlen(str)+1) { printf("%d ",Next[i]); }puts(""); } return 0; }
HDU Count the string+Next数组测试函数
标签:
原文地址:http://www.cnblogs.com/s1124yy/p/5666838.html