zoukankan      html  css  js  c++  java
  • 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
    ",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;
        }
    }
  • 相关阅读:
    break (Statements) – JavaScript 中文开发手册
    :first-of-type (Selectors) – CSS 中文开发手册
    no-new-symbol (Rules) – Eslint 中文开发手册
    Null-terminated byte strings (Strings) – C 中文开发手册
    HTML DOM Time 对象
    Java 实例 – 向文件中追加数据
    HTML DOM Hidden type 属性
    在Java中扩展原始转换
    字体变位 | font-variant-position (Fonts) – CSS 中文开发手册
    逆波兰计算器完整版
  • 原文地址:https://www.cnblogs.com/Tianwell/p/11240891.html
Copyright © 2011-2022 走看看