zoukankan      html  css  js  c++  java
  • 【JZOJ4886】【NOIP2016提高A组集训第13场11.11】字符串

    题目描述

    某日mhy12345在教同学们写helloworld,要求同学们用程序输出一个给定长度的字符串,然而发现有些人输出了一些“危险”的东西,所以mhy12345想知道对于任意长度n的小写字母字符串,不包含危险串的字符串个数

    数据范围

    对于10%的数据,|str|=1
    对于另30%的数据,n<=5
    对于另30%的数据,危险串不存在相同字符
    对于100%的数据,0<=|str|<=100,0<=n<=10000

    解法

    动态规划。
    设f[i][j]表示到第i个字母,匹配到危险串的第j个字符。
    显然

    f[i][j]f[i+1][pos[j][k]]

    pos[i][j]表示使用j这个字符匹配错误串,fail到的位置。
    这个东西可以使用KMP得出。

    代码

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    #define write(x) (cout<<(x)<<" ")
    #define writeln(x) (cout<<(x)<<endl)
    #define ll long long
    using namespace std;
    const char* fin="helloworld.in";
    const char* fout="helloworld.out";
    const ll inf=0x7fffffff;
    const ll maxn=10007,maxm=107,mo=1000000007;
    ll n,m,i,j,k,ans;
    char a[maxm];
    ll f[maxn][maxm];
    ll p[maxn],pos[maxm][26];
    ll read(){
        ll x=0,y=0;
        char ch=getchar();
        while (ch<'0' || ch>'9'){
            ch=getchar();
            if (++y==10) return -1;
        }
        while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
        return x;
    }
    ll qpower(ll a,ll b){
        ll c=1;
        while (b){
            if (b&1) c=c*a%mo;
            a=a*a%mo;
            b>>=1;
        }
        return c;
    }
    bool prepare(){
        memset(f,0,sizeof(f));
        memset(a,0,sizeof(a));
        scanf("%s",a+1);
        m=strlen(a+1);
        if (a[1]<'a' || a[1]>'z'){
            ans=qpower(26,n);
            writeln(ans);
            n=0;
            for (i=1;i<=m;i++) n=n*10+a[i]-'0';
            return false;
        }else return true;
    }
    void kmp(){
        j=0;
        for (i=2;i<=m;i++){
            while (j && a[j+1]!=a[i]) j=p[j];       
            if (a[j+1]==a[i]) j++;
            p[i]=j;
        }
        for (i=0;i<m;i++)
            for (j='a';j<='z';j++){
                k=i;
                while (k && a[k+1]!=j) k=p[k];
                if (a[k+1]==j) pos[i][j-'a']=k+1;
                else pos[i][j-'a']=0;
            }
    }
    int main(){
        freopen(fin,"r",stdin);
        freopen(fout,"w",stdout);
        n=0;
        while (1){
            if (!n) n=read();
            if (n==-1) break;
            if (prepare()){
                kmp();
                f[0][0]=1;
                for (i=0;i<n;i++)
                    for (j=0;j<m;j++)
                        for (k=0;k<26;k++){
                            f[i+1][pos[j][k]]=(f[i+1][pos[j][k]]+f[i][j])%mo;
                        }
                ans=0;
                for (i=0;i<m;i++) ans=(ans+f[n][i])%mo;
                writeln(ans);
                n=0;
            }
        }
        return 0;
    }
  • 相关阅读:
    java 堆、栈、方法区/ 类变量、成员变量、局部变量
    native的详细用法
    《Java项目中classpath路径详解》
    事务四大特征:原子性,一致性,隔离性和持久性(ACID)
    Tomcat 配置文件server.xml详解
    linux下vim常用命令 (更新中...)
    #1572 小Hi与花盆
    leetcode 120. Triangle
    leetcode 174. Dungeon Game
    leetcode 368. Largest Divisible Subset
  • 原文地址:https://www.cnblogs.com/hiweibolu/p/6714838.html
Copyright © 2011-2022 走看看