习题:DNA Sequence(AC自动机)

题目

传送门

思路

算是AC自动机的一个经典的应用

不包含其中的任何一个字串,也就是不能再自动机上面进行匹配

只要在自动机上走的路径不包含任何一个终结节点就行了

按照常规做法,建矩阵跑快速幂

代码

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int mod=100000;
struct ac_auto
{
	struct node
	{
		int end;
		int fail;
		int vis[5];
	}tre[105];
	struct matrix
	{
		int n;
		long long a[105][105];
		matrix(){memset(a,0,sizeof(a));}
		friend matrix operator * (const matrix &a,const matrix &b)
		{
			matrix c;
			c.n=a.n;
			for(int i=0;i<=a.n;i++)
			{
				for(int j=0;j<=b.n;j++)
				{
					for(int k=0;k<=a.n;k++)
					{
						c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
					}
				}
			}
			return c;
		}
	};
	int cnt;
	void init()
	{
		for(int i=0;i<=cnt;i++)
		{
			tre[i].end=tre[i].fail=0;
			for(int j=0;j<4;j++)
				tre[i].vis[j]=0;
		}
		cnt=0;
	}
	void insert(char s[])
	{
		int lens=strlen(s);
		int now=0;
		for(int i=0;i<lens;i++)
		{
			if(tre[now].vis[s[i]-'A']==0)
				tre[now].vis[s[i]-'A']=++cnt;
			now=tre[now].vis[s[i]-'A'];
		}
		tre[now].end=1;
	}
	void fail()
	{
		queue<int> q;
		for(int i=0;i<4;i++)
		{
			if(tre[0].vis[i])
			{
				tre[tre[0].vis[i]].fail=0;
				q.push(tre[0].vis[i]);
			}
		}
		while(!q.empty())
		{
			int u=q.front();
			q.pop();
			for(int i=0;i<4;i++)
			{
				if(tre[u].vis[i])
				{
					tre[tre[u].vis[i]].fail=tre[tre[u].fail].vis[i];
					q.push(tre[u].vis[i]);
				}
				else
					tre[u].vis[i]=tre[tre[u].fail].vis[i];
				tre[tre[u].vis[i]].end=max(tre[tre[u].vis[i]].end,tre[tre[tre[u].fail].vis[i]].end);
			}
		}
	}
	matrix qkpow(matrix a,long long b)
	{
		if(b==1)
			return a;
		matrix t=qkpow(a,b/2);
		t=t*t;
		if(b%2==1)
			t=t*a;
		return t;
	}
	int solve(long long n)
	{
		long long ans=0;
		matrix ret;
		matrix ini;
		ret.n=cnt;
		ini.n=cnt;
		for(int i=0;i<=cnt;i++)
		{
			ini.a[i][i]=1;
			if(tre[i].end)
				continue;
			for(int j=0;j<4;j++)
				if(tre[tre[i].vis[j]].end==0)
					ret.a[i][tre[i].vis[j]]++;
		}
		/*for(int i=0;i<=cnt;i++)
		{
			for(int j=0;j<=cnt;j++)
			{
				cout<<ret.a[i][j]<<' ';
			}
			cout<<'\n';
		}*/
		ret=qkpow(ret,n);

		ret=ini*ret;
		/*for(int i=0;i<=cnt;i++)
		{
			for(int j=0;j<=cnt;j++)
			{
				cout<<ret.a[i][j]<<' ';
			}
			cout<<'\n';
		}*/
		for(int i=0;i<=cnt;i++)
			ans=(ans+ret.a[0][i])%mod;
		return ans;
	}
}ac;
int m;
int hashh[128];
long long n;
char s[5];
int main()
{
	hashh['A']='A';
	hashh['C']='B';
	hashh['T']='C';
	hashh['G']='D';
	while(cin>>m>>n)
	{
		ac.init();
		for(int i=1;i<=m;i++)
		{
			cin>>s;
			for(int j=0;j<strlen(s);j++)
				s[j]=hashh[s[j]];
			ac.insert(s);
		}
		ac.fail();
		cout<<ac.solve(n)<<'\n';
	}
	
	return 0;
}
posted @ 2020-03-01 11:21  loney_s  阅读(304)  评论(0)    收藏  举报