hdu3666 Count the string

来源:互联网 发布:电力 大数据 编辑:程序博客网 时间:2024/06/05 15:38


题意:给你一个字符串,例如abab,他的前缀有a,ab,aba,abab,求这些前缀在串中能被匹配的次数。abab 就是 2+2+1+1=6.这题数据很弱,例如 5 aaaaa的数据应该是15 8 abababab应该是 20

思路:数据很弱,所以可以暴力(O^2),做法是先扫一遍与第一个相同的位置记录下来,将记录的位置作为起点比较串下一位,相同就记录,依次从串的第一个到最后一个。

#include<bits/stdc++.h>using namespace std;const int maxn=200000+10,mod=10007;char s[maxn];int main(){    int T;scanf("%d",&T);    while(T--){        int len;        scanf("%d %s",&len,s);        int b[len+1];        int t=0,ans=0;        for(int i=0;i<len;i++){            if(s[i]==s[0]){                ans=(ans+1)%mod;                b[t++]=i;            }        }        for(int i=1;i<len;i++){            int temp=t;            t=0;            for(int j=0;j<temp;j++){                if(s[b[j]+1]==s[i]){                    b[t++]=b[j]+1;                    ans=(ans+1)%mod; }            }        }        printf("%d\n",ans%mod);    }}

借助kmp算法的next[]数组可以优化到O(n),next[i]表示前i-1位的子串出现前后缀相等的位置。我们设num[i]表示前-1子串里前缀出现匹配的个数。

我们有转移方程: num[i]=num[next[i]]+1;

#include<bits/stdc++.h>using namespace std;const int maxn=200010,mod=10007;int Next[maxn],num[maxn];char s[maxn];void get_next(char *s,int *nxt,int len){   memset(nxt,0,sizeof(nxt));   nxt[0]=-1;   int i=0,j=-1;   while(i<len){      if(j==-1||s[i]==s[j]) nxt[++i]=++j;      else j=nxt[j];   }}int main(){    int T;scanf("%d",&T);    while(T--){        int len;scanf("%d",&len);        scanf("%s",s);        get_next(s,Next,len);        memset(num,0,sizeof(num));        int ans=0;        for(int i=1;i<=len;i++){            num[i]=(num[Next[i]]+1)%mod;            ans=(ans+num[i])%mod;        }        printf("%d\n",ans);    }}


0 0