• [codeforces] 633C Spy Syndrome 2


    原题

    Trie树+dp
    首先,我们可以简单的想到一种dp方式,就是如果这一段可以匹配并且可以与前一段接上,那么更新dp[i]为当前字符串的编号,然后倒推就可以得到答案。
    但是,显然我们不能O(m)比较,那么怎么办呢?
    这时候就可以体现Trie树的意义了,我们在爬Trie树的过程中就可以完成判断所有合法的字符串。当我们可以更新一个dp的时候就break就好了。

    #include<cstdio>
    #include<cstring>
    #include<vector>
    #define M 1001000
    #define N 10010
    using namespace std;
    int n,m,dp[M],l[M],cnt=2,now,ll,pos[M];
    char s[M],t[M];
    vector <int> v;
    struct hhh
    {
        int son[26],is;
        hhh()
    	{
    	    is=0;
    	    memset(son,0,sizeof(son));
    	}
    }edge[M];
    
    void add(int x)
    {
        now=1;
        int q;
        for (int i=ll+1;i<=ll+l[x];i++)
        {
    	if (t[i]<'a') q='a'-'A';else q=0;
    	if (edge[now].son[t[i]-'a'+q]) now=edge[now].son[t[i]-'a'+q];
    	else
    	{
    	    edge[now].son[t[i]-'a'+q]=cnt++;
    	    now=edge[now].son[t[i]-'a'+q];
    	}
        }
        edge[now].is=x;
    }
    
    int main()
    {
        scanf("%d",&n);
        scanf("%s",s+1);
        scanf("%d",&m);
        for (int i=1;i<=m;i++)
        {
    	scanf("%s",t+ll+1);
    	pos[i]=ll+1;
    	l[i]=strlen(t+ll+1);
    	add(i);
    	ll+=l[i];
        }
        dp[0]=1;
        for (int i=1;i<=n;i++)
        {
    	now=1;
    	for (int j=1;j<=i && now;j++)
    	{
    	    now=edge[now].son[s[i-j+1]-'a'];
    	    if (edge[now].is && dp[i-j])
    	    {
    		dp[i]=edge[now].is;
    		break;
    	    }
    	}
        }
        for (int i=n;i>=1;i-=l[dp[i]])
    	v.push_back(dp[i]);
        int ss=v.size();
        for (int i=ss-1;i>=0;i--)
        {
    	for (int j=1;j<=l[v[i]];j++)
    	    putchar(t[pos[v[i]]+j-1]);
    	putchar(' ');
        }
        return 0;
    }
    
  • 相关阅读:
    HTML5之dir属性
    IPv4地址分类及子网划分
    二叉树的3种遍历
    js的点表示法和方括号表示法
    javascript-数组的常用方法
    第一编博文——漫长编程路
    使用qemu
    initial ram disk
    qemu常见选项解析
    cp和scp
  • 原文地址:https://www.cnblogs.com/mrha/p/7867439.html
Copyright © 2020-2023  润新知