• L语言


    题目描述

    标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的。现在你要处理的就是一段没有标点的文章。

    一段文章T是由若干小写字母构成。一个单词W也是由若干小写字母构成。一个字典D是若干个单词的集合。我们称一段文章T在某个字典D下是可以被理解的,是指如果文章T可以被分成若干部分,且每一个部分都是字典D中的单词。

    例如字典D中包括单词{‘is’, ‘name’, ‘what’, ‘your’},则文章‘whatisyourname’是在字典D下可以被理解的,因为它可以分成4个单词:‘what’, ‘is’, ‘your’, ‘name’,且每个单词都属于字典D,而文章‘whatisyouname’在字典D下不能被理解,但可以在字典D’=D+{‘you’}下被理解。这段文章的一个前缀‘whatis’,也可以在字典D下被理解,而且是在字典D下能够被理解的最长的前缀。

    给定一个字典D,你的程序需要判断若干段文章在字典D下是否能够被理解。并给出其在字典D下能够被理解的最长前缀的位置。

    输入格式

    输入文件第一行是两个正整数n和m,表示字典D中有n个单词,且有m段文章需要被处理。之后的n行每行描述一个单词,再之后的m行每行描述一段文章。

    其中1<=n, m<=20,每个单词长度不超过10,每段文章长度不超过1M。

    输出格式

    对于输入的每一段文章,你需要输出这段文章在字典D可以被理解的最长前缀的位置。


    反正我现在觉得自己那个诡诡奇奇的AC_自动机是错的
    #include<bits/stdc++.h>
    #define re return
    #define inc(i,l,r) for(int i=l;i<=r;++i)
    using namespace std;
    template<typename T>inline void rd(T&x)
    {
        char c;bool f=0;
        while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
        x=c^48;
        while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
        if(f)x=-x;
    }
    
    const int maxn=9000;
    int n,m,tot;
    int AC[maxn][26],ed[maxn],fail[maxn],f[1500000],dis[maxn];
    char s[1500000];
    
    inline void clean(int x)
    {
        inc(i,0,25)AC[x][i]=0;
        ed[x]=fail[x]=0;
    }
    
    inline void build()
    {
        int len=strlen(s);
        int now=0;
        inc(i,0,len-1)
        {
            if(!AC[now][s[i]-'a'])
            {
                AC[now][s[i]-'a']=++tot;
                clean(tot);
            }
            now=AC[now][s[i]-'a'];
        }
        ed[now]=1;
        dis[now]=len;
    }
    
    
    inline void Get_fail()
    {
        queue<int>Q;
        inc(i,0,25)
        {
            if(AC[0][i])
                Q.push(AC[0][i]);
        }
        while(!Q.empty())
        {
            int u=Q.front();
            Q.pop();
            inc(i,0,25)
            {
                if(AC[u][i])
                {
                    fail[AC[u][i]]=AC[fail[u]][i];
                    Q.push(AC[u][i]);
                }
                else AC[u][i]=AC[fail[u]][i];
            }
        }
    }
    
    inline void Get_ans()
    {
        int now=0,ans=0;
        int len=strlen(s+1);
        inc(i,1,len)
        {
            f[i]=0;
            now=AC[now][s[i]-'a'];
            for(int t=now;t;t=fail[t])
            if(ed[t])
            f[i]|=f[i-dis[t]];
            //如果这个位置的单词前的 f[i-dis[t]]是成立的 
            if(f[i])ans=i;
        }
        printf("%d
    ",ans) ;
    }
    int main()
    {
        freopen("in.txt","r",stdin);
        rd(n),rd(m);
        inc(i,1,n)
        {
            scanf("%s",s);
            build();
        }
        Get_fail();
        f[0]=1; 
        inc(i,1,m)
        {
            scanf("%s",s+1);
            Get_ans(); 
        }
        re 0;
    }

    还是trie树+dp比较暴力又安全

    #include<bits/stdc++.h>
    #define static
    #define re return
    #define supervisor liangsiyi
    #define inc(i,l,r) for(int i=l;i<=r;++i)
    #define dec(i,l,r) for(int i=l;i>=r;--i)
    using namespace std;
    const int N=1500000;
    
    int n,m,tot,sum,tree[260][26],val[250],p[N];
    char s[N];
    
    
    void insert()
    {
        int l=strlen(s),r=0,x;
        sum=max(l,sum);
        for(int i=0;i<l;r=tree[r][s[i]-'a'],++i)
            if(!tree[r][s[i]-'a'])
                tree[r][s[i]-'a']=++tot;
        val[r]=1;
    }
    
    void viv(int sss)
    {        
        int l=strlen(s+1),ans=0;
        p[0]=sss;
        inc(i,0,l)
        {
            if(p[i]!=sss)continue;else ans=i;
            int r=0;
            inc(j,i+1,l)
            {
                r=tree[r][s[j]-'a'];
                if(!r)break;
                if(val[r])p[j]=sss;    
            }        
        }    
        printf("%d
    ",ans);
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        inc(i,1,n){scanf("%s",s);insert();}    
        inc(i,1,m){scanf("%s",s+1);
        viv(i);}
        re 0;
    }
     
     
  • 相关阅读:
    IIs安装&发布&解决遇到的问题
    Silverlight RadChart :创建十字定位&圈选
    桌面小工具,网络时间表
    毕设之c#多线程学习(官方+转载)
    常用的sql语言基础(1)
    转:C# DataGridView控件清空数据出错解决方法
    转:DataTable的Compute方法的应用
    转:判断DATASET是否为空
    转:DataSet、DataTable、DataRow、DataColumn区别及使用实例
    转发:C#加密方法汇总
  • 原文地址:https://www.cnblogs.com/lsyyy/p/11375318.html
Copyright © 2020-2023  润新知