首页 > 其他 > 详细

无限链计数

时间:2020-01-06 22:53:42      阅读:106      评论:0      收藏:0      [点我收藏+]

1708:无限链计数

时间限制: 3000 ms         内存限制: 262144 KB

【题目描述】

你可以用前t个小写字母来组成两段都无限长的链.

要求这些链中不能出现n个给定的串中的任何一个,请问有多少个满足条件的不同的无限链呢?

两个相同的两端均无限长的链A和B需要满足的条件为A[i+k]=B[i]对于任意的i都成立,其中k为任意整数。

例如t=2,给定串为{ab,ba},那么只有 …aaa…与 …bbb…两个,如果给定串为{ab},则有…aaa…,…bbb…,…bbbbaaa…三个。

【输入】

第一行两个整数t和n,含义如题所述。

接下来n行每行一个字符串表示一个不能出现的串。

【输出】

输出一行一个整数表示答案,如果有无限多个输出-1,保证答案不超过231-1


【输入样例】

2 2
ab
ba

【输出样例】

2

【提示】

【数据规模与约定】

对于20%的数据,t≤2,n=1;

对于另外30%的数据,t≤2;

对于100%的数据,n≤1000,t≤6,每个给定的串长度不超过10。

 

【题解】

 

首先建立AC自动机。并对AC自动机求强连通分量。

 

发现如果有非简单环,则肯定是-1因为他可以在一个上跑无限圈在到另一个跑任意圈在回来跑无数圈。

 

还有就是一条路径上有>=3个环,则-1,(在第一个环上跑无限圈到第二个环跑任意圈,在第三个环跑无数圈)。

 

然后就是拓扑排序解决有多少条路径保证开头结尾都是环。

 

代码如下:

技术分享图片
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+5;
int n,m,dfn[N],low[N],cnt;
char c[12];
struct trie
{
    int er[6],fail,pan;
}a[N];
inline void insert()
{
    int len=strlen(c+1),now=0;
    for(int i=1;i<=len;i++)
    {
        if(!a[now].er[c[i]-a]) a[now].er[c[i]-a]=++cnt;
        now=a[now].er[c[i]-a];
    }
    a[now].pan=1;
}
queue <int> que;
inline void get_fail()
{
    for(int i=0;i<=n-1;i++)
        if(a[0].er[i])
            que.push(a[0].er[i]);
    while(!que.empty())
    {
        int now=que.front();que.pop();
        a[now].pan|=a[a[now].fail].pan;
        for(int i=0;i<=n-1;i++)
        {
            if(a[now].er[i])
            {
                a[a[now].er[i]].fail=a[a[now].fail].er[i];
                que.push(a[now].er[i]);
            }
            else 
                a[now].er[i]=a[a[now].fail].er[i];
        }
    }
}
//aczidongji
//-----------------------------------------------
//tarjan
struct pigu
{
    int dao,ne;
}aa[N*10],b[N*10];
int last1[N],last2[N],top,size1,panh[N],siz,cnt1,size2,st[N],dui[N],bian[N],dian[N],ru[N],f[N],ge[N];
bool book[N];
inline void lingjiebiao1(int x,int y)
{
    aa[++size1].dao=y;
    aa[size1].ne=last1[x];
    last1[x]=size1;
}
inline void lingjiebiao2(int x,int y)
{
    b[++size2].dao=y;
    ru[y]++;
    b[size2].ne=last2[x];
    last2[x]=size2;
}
inline void dfs(int now)
{
    dfn[now]=low[now]=++cnt1;
    book[now]=1;st[++top]=now;
    for(int i=last1[now];i;i=aa[i].ne)
    {
        if(dfn[aa[i].dao]==0)
        {
            dfs(aa[i].dao);
            low[now]=min(low[now],low[aa[i].dao]);
        }
        else
            if(book[aa[i].dao]==1)
                low[now]=min(low[now],dfn[aa[i].dao]);
    }
    if(low[now]==dfn[now])
    {
        int k;siz++;
        do
        {
            k=st[top--];
            book[k]=0;
            dui[k]=siz;
            dian[siz]++;
        }while(k!=now);
    }
}
inline int build_bian()
{
    for(int i=0;i<=cnt;i++)
    {
        if(a[i].pan==1) continue;
        for(int j=0;j<=n-1;j++)
        {
            if(a[a[i].er[j]].pan) continue;
            lingjiebiao1(i,a[i].er[j]);
        }
    }
    for(int i=0;i<=cnt;i++)
        if(dfn[i]==0&&!a[i].pan) dfs(i);
    for(int i=0;i<=cnt;i++)
        for(int j=last1[i];j;j=aa[j].ne)
            if(dui[i]!=dui[aa[j].dao])
                lingjiebiao2(dui[i],dui[aa[j].dao]);
            else
                bian[dui[i]]++;
    for(int i=1;i<=siz;i++)
        if(bian[i]>dian[i])
        {
            cout<<"-1";
            return 0;
        }
        else    
            if(bian[i]==dian[i]) panh[i]=1;
}
inline void tuopu()
{
    for(int i=1;i<=siz;i++) if(ru[i]==0) que.push(i),ge[i]=panh[i];
    while(!que.empty())
    {
        int now=que.front();que.pop();
        if(ge[now]>=3)
        {
            cout<<"-1";
            return;
        }
        if(panh[now]) f[now]++;
        for(int i=last2[now];i;i=b[i].ne)
        {
            f[b[i].dao]+=f[now];
            ru[b[i].dao]--;
            if(ru[b[i].dao]==0) que.push(b[i].dao);
            ge[b[i].dao]=max(ge[b[i].dao],ge[now]+panh[b[i].dao]);
        }
    }
    int ans=0;
    for(int i=1;i<=siz;i++) if(panh[i]) ans+=f[i];
    cout<<ans;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%s",c+1);
        insert(); 
    }
    get_fail();
    if(build_bian()==0) return 0;
    tuopu();
    return 0;
}
View Code

无限链计数

原文:https://www.cnblogs.com/betablewaloot/p/12158505.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!