zoukankan      html  css  js  c++  java
  • BZOJ 2085 luogu P3502 [POI2010]Hamsters (KMP、Floyd、倍增)

    数组开小毁一生……

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2085

    这题在洛谷上有个条件是“互不包含”,其实bzoj的数据也满足这个条件,否则我目前已知的所有做法都是错的。

    个人觉得AC自动机可以用其他办法做,但是没试过

    KMP(或者hash), (f[i][j])表示(i)完了接上(j)需要多少个字符,直接用KMP求出最长的同时是(j)串的前缀和(i)串的后缀的串即可

    然后求走((m-1))步的最短路,倍增Floyd

    并不是多串匹配一定要用AC自动机!即使不考虑正确性,AC自动机的Trie树在复杂度上可能还多个字符集大小,不一定比KMP快,一定要合理选择!

    代码

    KMP:

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #define llong long long
    using namespace std;
    
    const int N = 200;
    const int S = 26;
    const int L = 1e5+1e3;
    const int LGM = 30;
    const llong INF = 1e17;
    llong f[N+3][N+3],g[N+3][N+3],g0[N+3][N+3];
    char a[L+3];
    int nxt[L+3];
    int len[L+3];
    int slen[L+3];
    int n; llong m;
    
    void update(llong &x,llong y) {x = min(x,y);}
    
    int KMP(char str1[],char str2[],int len1,int len2)
    {
    	for(int i=0; i<=len1; i++) nxt[i] = 0;
    	for(int i=2; i<=len1; i++)
    	{
    		nxt[i] = nxt[i-1];
    		while(nxt[i]!=0 && str1[i]!=str1[nxt[i]+1])
    		{
    			nxt[i] = nxt[nxt[i]];
    		}
    		if(str1[i]==str1[nxt[i]+1]) nxt[i]++;
    	}
    	if(str1==str2)
    	{
    		return len1-nxt[len1];
    	}
    	else
    	{
    		int j = 0;
    		for(int i=1; i<=len2; i++)
    		{
    			while(j && str1[j+1]!=str2[i])
    			{
    				j = nxt[j];
    			}
    			if(j<len1 && str1[j+1]==str2[i]) j++;
    		}
    		return len1-j;
    	}
    }
    
    int main()
    {
    	scanf("%d%lld",&n,&m);
    	for(int i=1; i<=n; i++)
    	{
    		scanf("%s",a+slen[i-1]+1); len[i] = strlen(a+slen[i-1]+1); slen[i] = slen[i-1]+len[i]+1; a[slen[i]] = ' ';
    	}
    	for(int i=1; i<=n; i++) {for(int j=1; j<=n; j++) {f[i][j] = g0[i][j] = g[i][j] = INF;}}
    	for(int i=1; i<=n; i++) f[i][i] = len[i];
    	for(int i=1; i<=n; i++)
    	{
    		for(int j=1; j<=n; j++)
    		{
    			g0[j][i] = KMP(a+slen[i-1],a+slen[j-1],len[i],len[j]);
    		}
    	}
    	/*
    	for(int i=1; i<=n; i++)
    	{
    		for(int j=1; j<=n; j++)
    		{
    			printf("g0: %d %d %lld
    ",i,j,g0[i][j]);
    		}
    	}
    	*/
    	m--;
    	while(m>0)
    	{
    		if(m&1)
    		{
    			for(int k=1; k<=n; k++)
    			{
    				for(int i=1; i<=n; i++)
    				{
    					for(int j=1; j<=n; j++)
    					{
    						update(g[i][j],f[i][k]+g0[k][j]);
    					}
    				}
    			}
    			for(int i=1; i<=n; i++)
    			{
    				for(int j=1; j<=n; j++)
    				{
    					f[i][j] = g[i][j];
    					g[i][j] = INF;
    				}
    			}
    		}
    		for(int k=1; k<=n; k++)
    		{
    			for(int i=1; i<=n; i++)
    			{
    				for(int j=1; j<=n; j++)
    				{
    					update(g[i][j],g0[i][k]+g0[k][j]);
    				}
    			}
    		}
    		for(int i=1; i<=n; i++)
    		{
    			for(int j=1; j<=n; j++)
    			{
    				g0[i][j] = g[i][j];
    				g[i][j] = INF;
    			}
    		}
    		m>>=1;
    	}
    	llong ans = INF;
    	for(int i=1; i<=n; i++)
    	{
    		for(int j=1; j<=n; j++)
    		{
    			ans = min(ans,f[i][j]);
    		}
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    

    AC自动机WA+TLE代码

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<vector>
    #define llong long long
    using namespace std;
    
    const int N = 200;
    const int S = 26;
    const int L = 1e5+1;
    const int LGM = 30;
    const llong INF = 1e17;
    void update(llong &x,llong y) {x = min(x,y);}
    llong g0[N+3][N+3],g[N+3][N+3],f[N+3][N+3];
    int len[N+3];
    int fail[L+3];
    int son[L+3][S+3];
    int idpos[N+3];
    char a[L+3];
    int id[L+3];
    int que[L+3];
    int dep[L+3];
    int n,rtn,siz; llong m;
    
    void insertstr(char str[],int sid)
    {
    	int u = rtn;
    	for(int i=1; i<=len[sid]; i++)
    	{
    		if(son[u][str[i]])
    		{
    			u = son[u][str[i]];
    		}
    		else
    		{
    			siz++; son[u][str[i]] = siz;
    			u = siz;
    		}
    	}
    	id[u] = sid;
    	idpos[sid] = u;
    }
    
    void add(int u,int v,llong w)
    {
    	update(g0[id[u]][id[v]],w);
    }
    
    void getfail()
    {
    	int head = 1,tail = 0;
    	for(int i=1; i<=S; i++)
    	{
    		int v = son[rtn][i];
    		if(v)
    		{
    			tail++; que[tail] = v;
    			fail[v] = rtn;
    		}
    	}
    	while(head<=tail)
    	{
    		int u = que[head]; head++;
    		for(int i=1; i<=S; i++)
    		{
    			int v = son[u][i];
    			if(v) {fail[son[u][i]] = son[fail[u]][i]; tail++; que[tail] = v;}
    			else {son[u][i] = son[fail[u]][i];}
    		}
    	}
    }
    
    void bfs(int s)
    {
    	printf("bfs(%d)
    ",s);
    	for(int i=1; i<=siz; i++) dep[i] = 0;
    	int head = 1,tail = 1; que[1] = s;
    	while(head<=tail)
    	{
    		int u = que[head]; head++;
    		int v = fail[i];
    		for(int i=1; i<=S; i++)
    		{
    			v = son[u][i];
    			if(v && dep[v]==0)
    			{
    				dep[v] = dep[u]+1;
    				add(s,v,dep[v]);
    				tail++; que[tail] = v;
    			}
    		}
    	}
    }
    
    int main()
    {
    	scanf("%d%lld",&n,&m); rtn = siz = 0;
    	for(int i=1; i<=n; i++)
    	{
    		scanf("%s",a+1); len[i] = strlen(a+1);
    		for(int j=1; j<=len[i]; j++) a[j] -= 96;
    		insertstr(a,i);
    	}
    	getfail();
    	for(int i=0; i<=siz; i++) printf("AC%d fail%d
    ",i,fail[i]);
    	for(int i=0; i<=siz; i++) {for(int j=1; j<=S; j++) {if(son[i][j]) {printf("son[%d][%c]=%d
    ",i,j+96,son[i][j]);}}}
    	for(int i=1; i<=n; i++) {for(int j=1; j<=n; j++) {f[i][j] = g0[i][j] = g[i][j] = INF;}}
    	for(int i=1; i<=n; i++) f[i][i] = 0ll;
    	for(int i=1; i<=siz; i++)
    	{
    		if(id[i])
    		{
    			bfs(i);
    		}
    	}
    	/*
    	for(int i=1; i<=n; i++)
    	{
    		for(int j=1; j<=n; j++)
    		{
    			printf("g0: %d %d %lld
    ",i,j,g0[i][j]);
    		}
    	}
    	*/
    	m--;
    	while(m>0)
    	{
    		if(m&1)
    		{
    			for(int k=1; k<=n; k++)
    			{
    				for(int i=1; i<=n; i++)
    				{
    					for(int j=1; j<=n; j++)
    					{
    						update(g[i][j],f[i][k]+g0[k][j]);
    					}
    				}
    			}
    			for(int i=1; i<=n; i++)
    			{
    				for(int j=1; j<=n; j++)
    				{
    					f[i][j] = g[i][j];
    					g[i][j] = INF;
    				}
    			}
    		}
    		for(int k=1; k<=n; k++)
    		{
    			for(int i=1; i<=n; i++)
    			{
    				for(int j=1; j<=n; j++)
    				{
    					update(g[i][j],g0[i][k]+g0[k][j]);
    				}
    			}
    		}
    		for(int i=1; i<=n; i++)
    		{
    			for(int j=1; j<=n; j++)
    			{
    				g0[i][j] = g[i][j];
    				g[i][j] = INF;
    			}
    		}
    		m>>=1;
    	}
    	llong ans = INF;
    	for(int i=1; i<=n; i++)
    	{
    		for(int j=1; j<=n; j++)
    		{
    			ans = min(ans,len[i]+f[i][j]);
    		}
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    /*
    4 11
    aaaaaaa
    aaaa
    aaaaaa
    aaaaaaaaaa
    */
    
  • 相关阅读:
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 88怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 81.0怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 40怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 24.0怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 21.0怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下驱动器试运行提示过速度保护怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下驱动器如何执行绝对值清零
    倍福TwinCAT(贝福Beckhoff)基础教程 松下绝对值驱动器如何做初始化设置
    倍福TwinCAT(贝福Beckhoff)基础教程 松下官方软件开启报错伺服未就绪怎么办
    JAVA Eclipse 启动 Eclipse 弹出“Failed to load the JNI shared library jvm_dll”怎么办
  • 原文地址:https://www.cnblogs.com/suncongbo/p/11038876.html
Copyright © 2011-2022 走看看