zoukankan      html  css  js  c++  java
  • 雅礼集训【Day6-1】字符串

    雅礼集训【Day6-1】字符串

    img

    假设我们有串(a),我们设(a')(a)翻转后按为取反过后的串。

    我们只考虑前一半的,长为(m)的串。如果前半截匹配了(a)或者(a'),则(a)就被匹配上了。所以我们记(f_{i,j,S})表示长度(i),在AC自动机上匹配到了(j)节点,已经匹配了的串的集合为(S)的方案数。

    但是可能会出现(a)出现的位置跨越了(m),这样我们就会出问题。因为我们记录了生成的串在AC自动机上匹配的节点,所以我们就能得到(a)在前半截中匹配的长度。如果这个长度(geqlfloor frac{len}{2} floor),则我们能知道后半截是什么,也就能判断是否合法了。

    那如果(a)没有匹配长度(geqlfloor frac{len}{2} floor)的情况呢?我们发现,此时(a')的匹配长度一定(geqlfloor frac{len}{2} floor),所以我们同时判断(a)(a'),其中一个成立就行了。

    代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define N 2005
    #define M 505
    
    using namespace std;
    inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}
    
    const ll mod=998244353;
    int n,m;
    string str[20];
    struct trie {
    	int ch[2];
    	int w;
    	int fail;
    	int flag;
    	int len;
    }tr[N];
    
    int rt=1;
    int cnt=1;
    void Insert(string s,int id) {
    	int len=s.length();
    	int v=1;
    	for(int i=0;i<len;i++) {
    		int j=s[i]-'0';
    		if(!tr[v].ch[j]) {
    			tr[v].ch[j]=++cnt;
    			tr[tr[v].ch[j]].len=tr[v].len+1;
    		}
    		v=tr[v].ch[j];
    	}
    	tr[v].w|=1<<id-1;
    }
    
    queue<int>q;
    void build_fail() {
    	for(int i=0;i<2;i++) {
    		if(!tr[1].ch[i]) tr[1].ch[i]=1;
    		else {
    			int x=tr[1].ch[i];
    			tr[x].fail=1;
    			q.push(x);
    		}
    	}
    	while(!q.empty()) {
    		int v=q.front();
    		q.pop();
    		tr[v].w|=tr[tr[v].fail].w;
    		for(int i=0;i<2;i++) {
    			if(!tr[v].ch[i]) tr[v].ch[i]=tr[tr[v].fail].ch[i];
    			else {
    				int sn=tr[v].ch[i];
    				int f=tr[v].fail;
    				tr[sn].fail=tr[f].ch[i];
    				q.push(sn);
    			}
    		}
    	}
    }
    int pre[20][N];
    int f[M][1205][1<<6];
    bool pd(string &a,int len,int v,int id) {
    	int now=1;
    	tr[1].flag=1;
    	for(int i=0;i<len;i++) {
    		now=tr[now].ch[a[i]-'0'];
    		tr[now].flag=1;
    	}
    	while(!tr[v].flag) v=tr[v].fail;
    	int nlen=0;
    	now=1;
    	for(int i=0;i<len&&now!=v;i++,nlen++) {
    		now=tr[now].ch[a[i]-'0'];
    	}
    	int flag=0;
    	while(v) {
    		if(tr[v].flag&&pre[id][tr[v].len]) flag=1;
    		v=tr[v].fail;
    	}
    	tr[1].flag=0;
    	now=1;
    	for(int i=0;i<len;i++) {
    		now=tr[now].ch[a[i]-'0'];
    		tr[now].flag=0;
    	}
    	return flag;
    }
    
    bool chk(int v,int S) {
    	for(int i=1;i<=n;i++) {
    		if(S>>i-1&1) continue ;
    		int len=str[i].length();
    		if(!pd(str[i],len,v,i)&&!pd(str[i+n],len,v,i+n)) return 0;
    	}
    	return 1;
    }
    
    int main() {
    	n=Get(),m=Get();
    	for(int i=1;i<=n;i++) cin>>str[i];
    	for(int i=1;i<=n;i++) {
    		int len=str[i].length();
    		for(int j=len-1;j>=0;j--) {
    			str[i+n].push_back(str[i][j]^1);
    		}
    	}
    	for(int i=1;i<=n;i++) {
    		Insert(str[i],i);
    		Insert(str[i+n],i);
    	}
    	build_fail();
    	f[0][1][0]=1;
    	for(int i=0;i<m;i++) {
    		for(int j=1;j<=cnt;j++) {
    			for(int S=0;S<1<<n;S++) {
    				if(!f[i][j][S]) continue ;
    				for(int k=0;k<2;k++) {
    					int to=tr[j].ch[k];
    					(f[i+1][to][S|tr[to].w]+=f[i][j][S])%=mod;
    				}
    			}
    		}
    	}
    	
    	for(int i=1;i<=2*n;i++) {
    		int len=str[i].length();
    		for(int st=1;st<=len;st++) {
    			if(st*2<len) continue ;
    			int flag=1;
    			for(int j=st;j<len;j++) {
    				if(str[i][j]==str[i][2*st-j-1]) flag=0;
    			}
    			pre[i][st]=flag;
    		}
    	}
    	
    	int ans=0;
    	for(int i=1;i<=cnt;i++) {
    		for(int S=0;S<1<<n;S++) {
    			if(!f[m][i][S]) continue ;
    			if(chk(i,S)) {
    				(ans+=f[m][i][S])%=mod;
    			}
    		}
    	}
    	cout<<ans;
    	return 0;
    }
    
    
  • 相关阅读:
    771. Jewels and Stones
    706. Design HashMap
    811. Subdomain Visit Count
    733. Flood Fill
    117. Populating Next Right Pointers in Each Node II
    250. Count Univalue Subtrees
    94. Binary Tree Inorder Traversal
    116. Populating Next Right Pointers in Each Node
    285. Inorder Successor in BST
    292. Nim Game Java Solutin
  • 原文地址:https://www.cnblogs.com/hchhch233/p/10616091.html
Copyright © 2011-2022 走看看