码迷,mamicode.com
首页 > 其他好文 > 详细

#552. 【UNR #4】同构判定鸭

时间:2020-09-12 21:43:37      阅读:46      评论:0      收藏:0      [点我收藏+]

标签:维数   长度   合并   ++   mic   向量   utc   空间   code   

题目描述

技术图片
技术图片

题解

结论:坏串长度<=n1+n2

口胡证明:

把两个图合并,第二个图的标号加上n1,状态可以看作一个长度位n1+n2的向量,转移看作26个矩阵,不同位的不同字母的值不同(随机),基本可以视作哈希值与串一一对应

称一些串组成的集合为向量空间,一个向量空间的维数等价于线性无关组大小

每次转移等于把集合U或上U*转移矩阵,如果向量空间里面存在某个向量点乘上一个前n1个为1后n2个为-1的向量非0则对应一个坏串

每次转移之后的向量空间U1,U2,U3...满足U1?U2?U3?...

结论:如果集合U?集合V那么满足V的维数>U或U=V,因为如果不相等那么V多出来的那部分一定有一个加到U里面维数会变大,因为U的意义实际上是长度<=某个数的串的集合,如果多了那么多的一定是更长的

那么U一定是维数不断增加,之后到某个时刻不变,因为转移不变所以之后的U全部相等了

又因为维数最多为n1+n2,所以假设存在坏串那一定可以在前n1+n2个U里找到(>n1+n2的和第n1+n2个相等)

找到长度之后按位确定即可,计算时每次加到串首即可做到O(26nm)

code

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define add(a,b) a=((a)+(b))%998244353
#define mod 998244353
#define ll long long
//#define file
using namespace std;

ll rd[1001][26],sum;
int i,j,k,l;
char ch;
struct G{
	int n,m,a[3001][3],ls[501],len,i,j,k,l;
	ll f[1001][501],g[501],G[501];
	char ch;
	
	void New(int x,int y,int z) {++len;a[len][0]=y;a[len][1]=ls[x];ls[x]=len;a[len][2]=z;}
	void Read()
	{
		scanf("%d%d",&n,&m);
		fo(i,1,m) scanf("%d%d%c%c",&j,&k,&ch,&ch),New(j,k,ch-‘a‘);
	}
	void js(int t)
	{
		fo(i,1,n)
		{
			for (j=ls[i]; j; j=a[j][1])
			add(f[t][i],f[t-1][a[j][0]]*rd[t][a[j][2]]);
		}
	}
	void Js(int t,int c)
	{
		memset(G,0,sizeof(G));
		fo(i,1,n)
		{
			for (j=ls[i]; j; j=a[j][1])
			if (a[j][2]==c)
			add(G[a[j][0]],g[i]);
		}
	}
	void pd(int t,int s) {fo(i,1,n) add(sum,G[i]*f[t][i]*s);}
	void change() {fo(i,1,n) g[i]=G[i];}
} g1,g2;

ll random(int x,int y) {return (1ll*rand()*23333+rand())%(y-x+1)+x;}

int main()
{
	#ifdef file
//	freopen("uoj552.in","r",stdin);
	freopen("ex_string4.in","r",stdin);
	#endif
	
	srand(time(NULL));
	g1.Read(),g2.Read();
	fo(i,1,g1.n+g2.n) fo(j,0,25) rd[i][j]=random(1,mod-1);
	fo(i,1,g1.n) g1.f[0][i]=g1.g[i]=1;
	fo(i,1,g2.n) g2.f[0][i]=g2.g[i]=1;
	
	fo(i,1,g1.n+g2.n)
	{
		g1.js(i),g2.js(i);
		sum=0;
		fo(j,1,g1.n) add(sum,g1.f[i][j]);
		fo(j,1,g2.n) add(sum,-g2.f[i][j]);
		
		if (sum)
		{
			l=i;
			fo(i,1,l)
			{
				fo(j,0,25)
				{
					sum=0;
					g1.Js(i,j),g2.Js(i,j);
					g1.pd(l-i,1),g2.pd(l-i,-1);
					if (sum)
					{
						g1.change(),g2.change();
						putchar(j+‘a‘);
						break;
					}
				}
			}
			return 0;
		}
	}
	printf("Same\n");
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}

#552. 【UNR #4】同构判定鸭

标签:维数   长度   合并   ++   mic   向量   utc   空间   code   

原文地址:https://www.cnblogs.com/gmh77/p/13592129.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!