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;
        }
    }
  • 相关阅读:
    java socket HTTPClient GET
    Spring的JdbcTemplate使用update或insert操作的三种使用例子
    windows XP 解决QQ和360软件冲突的办法
    J2EE 应用服务器集群常用方法
    javaeye被关闭了 被政 府和谐感
    P6SPY(JDBC SQL拦截)的安装和使用
    让QQ与360并存,不卸载360正常使用QQ
    Spring2.5注解(标注)学习笔记(使用annotation代替XML)
    centos vnc配置
    HTTP协议内容具体含义
  • 原文地址:https://www.cnblogs.com/Tianwell/p/11240891.html
Copyright © 2011-2022 走看看