您的位置:首页 > 其它

hdu 3336

2015-09-14 19:58 162 查看
<span style="background-color: rgb(0, 153, 0);">/*题意:就是让给你一个字符串,然后计算不断增加的前缀字符串在整个字符创当中出现的次数和,可能出现的次数过大,所以要求结果1007.
例如:abab a 2 ab 2 aba 1 abab 1  2+2+1+1=6
*/
/*思路:其实我们想想比如对于位置i来说,现在我们求出了f[i]的值,那么[0,f[i]-1]串就是一个
能匹配i-1位置的最长的前缀串。且我们根据f[i]的值可以定位其他所有可匹配的前缀。KMP的思想
就是找出每个位置i的可匹配最大前缀j。令dp[i]表示S[0,i-1]串的后缀能匹配的前缀个数,
那么dp[i]=dp[next[i]]+1, dp[1]=1正好表示串s[0]的后缀只能匹配串s[0].
*/</span>

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<int,int> pp;
#define inf 0x3f3f3f3f
#define eps 1e-10
#define maxl 200020
#define mem(i,j) memset(i,j,sizeof(i))
const int mod=10007;
int f[maxl],d[maxl],len;
char s[maxl];
void getnext(char *s,int *f){
f[0]=f[1]=0;
for(int i=1;i<len;i++){
int j=f[i];
while(j&&am
4000
p;s[i]!=s[j]) j=f[j];//这里不断的替换来降低复杂度
f[i+1]=(s[i]==s[j])?j+1:0;//f[i+1]保存的是s[i]的前缀的长度
}
}

int main()
{
//freopen("in.txt", "r", stdin);
int t;
cin>>t;
while(t--){
cin>>len>>s;
getnext(s,f);
memset(d,0,sizeof(d));
int ans=0;
for(int i=1;i<=len;i++){
d[i]=d[f[i]]+1;//因为f[i]记录的是i-1的前缀的长度 但是不知道它的次数 后面的是在前面的结果上面累加的 所以每次加1 直到后面如果还是有相同的前缀的时候已经累加上去了
ans=(ans+d[i])%mod;
}
cout<<ans<<endl;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: