• Jzoj3172 贴瓷砖


    A镇的主街是由N个小写字母构成,镇长准备在上面贴瓷砖,瓷砖一共有M种,第i种上面有Li个小写字母,瓷砖不能旋转也不能被分割开来,瓷砖只能贴在跟它身上的字母完全一样的地方,允许瓷砖重叠,并且同一种瓷砖的数量是无穷的。

    问街道有多少字母(地方)不能被瓷砖覆盖。、

    今天翻看题库发现这道题忘记写题解了。。。

    非常好的卡常题,题目也很裸,直接AC自动机+前缀和判定就好了,但是当时不知道为什么用了fenwick

    #include<queue>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define N 300010
    #define M 4000100
    using namespace std;
    int n,m,ans=0; char s[300010],t[5010];
    struct fenwick{
    	int w[N],S;
    	inline void add(int x,int v){ for(;x<=m;x+=x&-x) w[x]+=v; }
    	inline int sum(int x){ for(S=0;x;x&=x-1) S+=w[x]; return S; }
    }w;
    int fail[M],son[M][26],c[M],cnt=1,v[26];
    inline void insert(char* s){
    	int x=1,l=0;
    	for(;*s;++s,++l){
    		v[*s-'a']=1;
    		x=son[x][*s-'a']?son[x][*s-'a']:son[x][*s-'a']=++cnt;
    	}
    	c[x]=l;
    }
    inline void build(){
    	queue<int> q;
    	for(int i=0;i<26;++i)
    		if(!son[1][i]) son[1][i]=1;
    		else q.push(son[1][i]),fail[son[1][i]]=1;
    	for(int x;!q.empty();q.pop()){
    		x=q.front();
    		for(int i=0;i<26;++i)
    			if(!son[x][i]) son[x][i]=son[fail[x]][i];
    		else q.push(son[x][i]),fail[son[x][i]]=son[fail[x]][i];
    	}	
    }
    inline void query(char* s){
    	for(int i=1,x=1;*s;++s,++i){
    		x=son[x][*s-'a'];
    		for(int j=x;j!=1;j=fail[j])
    			if(c[j]){ w.add(i-c[j]+1,1); w.add(i+1,-1); }
    	}
    }
    int main(){
    	scanf("%d%s",&m,s);
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i){
    		scanf("%s",t); insert(t);
    	}
    	for(int i=0;i<m;++i) v[s[i]-'a']=0;
    	for(int i=0;i<26;++i) if(v[i]) goto end;
    	build(); query(s); end:
    	for(int i=1;i<=m;++i) if(w.sum(i)==0) ++ans;
    	printf("%d
    ",ans);
    }

  • 相关阅读:
    点餐系统的设计与实现注意点与解决办法
    不借助临时变量交换两个数值
    python2.7之乱码问题
    netty-学习笔记
    每天一个linux命令---curl
    每天一个linux命令---useradd
    webservice 学习笔记
    每天一个linux命令---kill
    XML解析
    每天一个linux命令---tar
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/9477155.html
Copyright © 2020-2023  润新知