zoukankan      html  css  js  c++  java
  • [NOI2011]阿狸的打字机

    Description
    阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机。打字机上只有28个按键,分别印有26个小写英文字母和'B'、'P'两个字母。
    经阿狸研究发现,这个打字机是这样工作的:
    l 输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最后)。
    l 按一下印有'B'的按键,打字机凹槽中最后一个字母会消失。
    l 按一下印有'P'的按键,打字机会在纸上打印出凹槽中现有的所有字母并换行,但凹槽中的字母不会消失。
    例如,阿狸输入aPaPBbP,纸上被打印的字符如下:a aa ab
    我们把纸上打印出来的字符串从1开始顺序编号,一直到n。打字机有一个非常有趣的功能,在打字机中暗藏一个带数字的小键盘,在小键盘上输入两个数(x,y)(其中1≤x,y≤n),打字机会显示第x个打印的字符串在第y个打印的字符串中出现了多少次。
    阿狸发现了这个功能以后很兴奋,他想写个程序完成同样的功能,你能帮助他么?

    Input
    输入的第一行包含一个字符串,按阿狸的输入顺序给出所有阿狸输入的字符。
    第二行包含一个整数m,表示询问个数。
    接下来m行描述所有由小键盘输入的询问。其中第i行包含两个整数x, y,表示第i个询问为(x, y)。

    Output
    输出m行,其中第i行包含一个整数,表示第i个询问的答案。

    Sample Input
    aPaPBbP
    3
    1 2
    1 3
    2 3

    Sample Output
    2
    1
    0

    HINT
    1<=N<=10^5
    1<=M<=10^5
    输入总长<=10^5


    AC自动机大神题,写完就毕业了

    首先构建AC自动机的Fail树,得出dfs序,得出每个结点进出时间(L[x],R[x])

    考虑这样一种暴力:对于一个询问x,y,查询自动机上root-y的每一个结点,沿着Fail指针是否会走到x的结尾点,如果可以即答案+1

    而在Fail树中,变为查询自动机上root-y的所有结点中,有多少个在x的子树中?

    只要在自动机上再重新走一遍,走到一个结点y,则将1-(L[y])都+1,解决询问x,y(把y相同的链表串起来),即查询(L[x])(R[x])的和。。。当遇到一个B时1-(L[y])都-1

    树状数组即可

    /*program from Wolfycz*/
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define inf 0x7f7f7f7f
    #define lowbit(x) ((x)&-(x))
    using namespace std;
    typedef long long ll;
    typedef unsigned int ui;
    typedef unsigned long long ull;
    inline char gc(){
    	static char buf[1000000],*p1=buf,*p2=buf;
    	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int frd(){
    	int x=0,f=1;char ch=gc();
    	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    inline void print(int x){
    	if (x<0)	putchar('-'),x=-x;
    	if (x>9)	print(x/10);
    	putchar(x%10+'0');
    }
    const int N=1e5;
    int L[N+10],R[N+10],Ans[N+10],Time;
    struct S1{
    	int pre[N+10],now[N+10],child[N+10],tot;
    	void join(int x,int y){pre[++tot]=now[x],now[x]=tot,child[tot]=y;}
    }A,B;
    struct S2{
    	int tree[(N<<1)+10];
    	void insert(int x,int v){for (;x<=Time;x+=lowbit(x))	tree[x]+=v;}
    	int Query(int x){
    		int res=0;
    		for (;x;x-=lowbit(x))	res+=tree[x];
    		return res;
    	}
    }BIT;
    struct S3{
    	int trie[N+10][26],fail[N+10],fa[N+10],pos[N+10];
    	int root,tot;
    	void insert(char *s){
    		int p=root,len=strlen(s),cnt=0;
    		for (int i=0;i<len;i++){
    			if (s[i]=='B')	p=fa[p];
    			else	if (s[i]=='P')	pos[++cnt]=p;
    			else{
    				if (!trie[p][s[i]-'a'])	fa[trie[p][s[i]-'a']=++tot]=p;
    				p=trie[p][s[i]-'a'];
    			}
    		}
    	}
    	void make_fail(){
    		static int h[N+10];
    		int head=1,tail=0;
    		for (int i=0;i<26;i++)	if (trie[root][i])	h[++tail]=trie[root][i];
    		for (;head<=tail;head++){
    			int Now=h[head];
    			for (int i=0;i<26;i++){
    				if (trie[Now][i]){
    					int son=trie[Now][i];
    					fail[son]=trie[fail[Now]][i];
    					h[++tail]=son;
    				}else	trie[Now][i]=trie[fail[Now]][i];
    			}
    		}
    	}
    	void solve(char *s){
    		int p=root,len=strlen(s),idx=0;
    		BIT.insert(L[p],1);
    		for (int i=0;i<len;i++){
    			if (s[i]=='P'){
    				++idx;
    				for (int p=B.now[idx],son=B.child[p];p;p=B.pre[p],son=B.child[p])
    					Ans[p]=BIT.Query(R[pos[son]])-BIT.Query(L[pos[son]]-1);
    			}else	if (s[i]=='B')	BIT.insert(R[p],-1),p=fa[p];
    			else	p=trie[p][s[i]-'a'],BIT.insert(L[p],1);
    		}
    	}
    }AC;//Aho-Corasick automaton
    void dfs(int x){
    	L[x]=++Time;
    	for (int p=A.now[x],son=A.child[p];p;p=A.pre[p],son=A.child[p])	dfs(son);
    	R[x]=++Time;
    }
    char s[N+10];
    int main(){
    	scanf("%s",s);
    	AC.insert(s);
    	AC.make_fail();
    	for (int i=1;i<=AC.tot;i++)	A.join(AC.fail[i],i);
    	dfs(AC.root);
    	int m=read();
    	for (int i=1;i<=m;i++){
    		int x=read(),y=read();
    		B.join(y,x);
    	}
    	AC.solve(s);
    	for (int i=1;i<=m;i++)	printf("%d
    ",Ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    Oracle常用命令大全(很有用,做笔记)
    表格驱动编程在代码中的应用
    mac 利用svn下载远程代码出现Agreeing to the Xcode/iOS license requires admin privileges, please re-run as root via sudo.
    FAILURE: Build failed with an exception.
    There is an internal error in the React performance measurement code.Did not expect componentDidMount timer to start while render timer is still in progress for another instance
    react native TypeError network request failed
    Android向系统相册中插入图片,相册中会出现两张 一样的图片(只是图片大小不一致)
    react-native Unrecognized font family ‘Lonicons’;
    react-native SyntaxError xxxxx/xx.js:Unexpected token (23:24)
    Application MyTest has not been registered. This is either due to a require() error during initialization or failure to call AppRegistry.registerComponent.
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/10574882.html
Copyright © 2011-2022 走看看