You have two strings SSS and TTT in all capitals.
Now an efficient program is required to maintain a operation and support a query.
The operation C i chC~i~chC i ch with given integer iii and capital letter chchch, changes the iii-th character of SSS into chchch.
The query Q i jQ~i~jQ i j asks the program to find out, in the substring of SSS from the iii-th character to the jjj-th one, the total number of TTT appearing.
Input Format
The first line contains an integer TTT, indicating that there are TTT test cases.
For each test case, the first line contains an integer N (N≤100000)N~(N \leq 100000)N (N≤100000).
The second line is the string S (∣S∣≤100000)S~(|S| \leq 100000)S (∣S∣≤100000) and the third line is the stringT (∣T∣≤10)T~(|T| \leq 10)T (∣T∣≤10).
Each of the following NNN lines provide a operation or a query as above descriptions.
Output Format
For each query, output an integer correponding to the answer.
Output an empty line after each test case.
样例输出
1 20
当时做的时候真的是毫无思绪,看了大家的代码之后才明白,居然是用线段树+暴力枚举.. 先暴力枚举所有的点是否匹配。匹配为1,不匹配为0.之后用这组数据进行建立线段树。 查询就是区间查询, 单点更新时,暴力枚举与更新点有关的,也就是附近的点,看看改完时候可以匹配,可以的话,把那个点改为1,不行就给为0;
学习点:对于大量的字符串匹配,一定不能使用暴力KMP。应该进行局部查询。而对于区间内求和,用 线段树来做。
借用http://blog.csdn.net/qq_37171272/article/details/77916215的代码.我用来查询
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<stack> #define maxn 100005 using namespace std; char str[maxn],s[maxn]; int arr[maxn],len,ll; void Getarr(char *str,char *s) { for(int i=0;i<len;i++) { int flag=1; for(int j=0;j<ll;j++) { if(str[i+j]!=s[j]||i+ll>len)//如果i+ll>len,说明到最后都不能构成T { flag=0; arr[i]=0; break; } } if(flag) arr[i]=1; } } struct node { int l; int r; int sum; }segtree[maxn*4]; void pushup(int root) { segtree[root].sum=segtree[root<<1].sum+segtree[root<<1|1].sum; } void build(int root,int l,int r) { segtree[root].l=l; segtree[root].r=r; if(l==r) { segtree[root].sum=arr[l]; return; } int mid=(l+r)>>1; build(root<<1,l,mid); build(root<<1|1,mid+1,r); pushup(root); } void update(int root,int p,int val) { int ll=segtree[root].l; int rr=segtree[root].r; if(ll==rr) { segtree[root].sum=val; return; } int mid=(ll+rr)>>1; if(p<=mid) update(root<<1,p,val); else update(root<<1|1,p,val); pushup(root); } int query(int root,int l,int r) { int ll=segtree[root].l; int rr=segtree[root].r; if(l<=ll&&rr<=r) return segtree[root].sum; int mid=(ll+rr)>>1; int ans=0; if(l<=mid) ans+=query(root<<1,l,r); if(r>mid) ans+=query(root<<1|1,l,r); return ans; } int main() { int t,n; scanf("%d",&t); while(t--) { scanf("%d%s%s",&n,str,s); len=strlen(str);ll=strlen(s); Getarr(str,s); build(1,0,len-1); while(n--) { char op[5],ch[3]; int x,y; scanf("%s",op); if(op[0]=='Q') { scanf("%d%d",&x,&y); if(y-x+1<ll){//查询求见长度比T字符串长度小,直接输出0 printf("0\n"); continue; } x--;y--; printf("%d\n",query(1,x,y-ll+1));//查询的右端点要减去T字符串的长度+1,想想为什么 } else { scanf("%d%s",&x,ch); x--; str[x]=ch[0]; int tmp=x-ll+1>=0?x-ll+1:0; for(int i=tmp;i<=x;i++) { int flag=1; for(int j=0;j<ll;j++) { if(str[i+j]!=s[j]||i+ll>len) { if(arr[i]!=0) update(1,i,0); arr[i]=0; flag=0; break; } } if(flag==1) { if(arr[i]!=1) update(1,i,1); arr[i]=1; } } } } cout<<endl; } return 0; }