HDU-3336 Count the string (KMP)

题意:T个问题,m为字符串长度,然后输出匹配所有前缀串出现个数之和,其中 mod为 10007

思路:一开始可以想到利用kmp匹配统计子字符串出现次数的模板 (用一个for循环来一个一个匹配)但是字符串长度为(1 <= n <= 200000) 所以for下去肯定会超时,所以我们尝试用dp解决(记录一些共同的信息)  我们设置dp[i]表示该字符串前i个字符中出现任意以第i个字符结尾的前缀的次数,next[i]是最长公共前后缀也是回溯距离。事实上这个也是 KMP对循环节处理部分的一个运用(回溯找到相同前后缀);

所以推出dp[i]=dp[next[i]]+1这样一个等式(就能减少重复匹配了);(上一个回溯字符尾部相同)

完整代码:

#include <iostream>
#include <cstring>
#include <cmath>
#define mod 10007
using namespace std;
const int maxn = 2e5+9;
int dp[maxn],nex[maxn];
char s[maxn];
int len1,len2;
void getnext(){
    int i=0,j=-1;
    nex[i] = j;
    while(i<len1){
        if(j==-1||s[i]==s[j]){
            nex[++i] = ++j;
        }else{
            j = nex[j];
        }
    }
}

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int sum = 0;
        scanf("%d",&len1);
        scanf("%s",&s);
        memset(dp,0,sizeof(dp));
        getnext(); 
        for(int i=1;i<=len1;i++){
            dp[i]=dp[nex[i]]+1;
            sum = (sum+dp[i])%mod;
        }
        printf("%d\n",sum);
    }
}

 

 

 

一开始写for循环的TLE代码:(记住字符串的TLE 问题以后不能再犯...)

#include <iostream>
#include <cstring>
#include <cmath>
#define mod 10007
using namespace std;
const int maxn = 2e5+9;

int nex[maxn];
char s[maxn];
char s1[maxn];
int len1,len2;
void getnext(){
    int i=0,j=-1;
    nex[i] = j;
    while(i<len1){
        if(j==-1||s[i]==s[j]){
            nex[++i] = ++j;
        }else{
            j = nex[j];
        }
    }
}
int kmp_count(){
    int ans = 0;
    int i= 0,j=0;
    for(i=0;i<len1;i++)
    {
        while(j>0&&s[i]!=s1[j])
            j=nex[j];
        if(s[i]==s1[j])    j++;
        if(j==len2)
        {
            ans++;
            j=nex[j];
        }
    }
    return ans;
}
int main(){
    int T;
    cin>>T;
    while(T--){
        int ans = 0;
        scanf("%d",&len1);
        scanf("%s",&s);
        getnext(); 
        for(int i=0;i<len1;i++){
            len2 = i+1;
            s1[i]=s[i];
            ans = (ans + kmp_count())% mod ;
        }
        cout<<ans<<endl;
    }
}

 

posted @ 2019-07-24 21:12  Tianwell  阅读(212)  评论(0编辑  收藏  举报