Non Super Boring Substring —— 馬拉車+樹狀陣列(求不包含迴文串區間的個數)
You’ll be given a string S and an integer K. You have to find the number of non super-boring substring inside S. A substring is called super-boring if it contains any palindromic substring of length ≥ K inside it. For example, if S = “ababba” and K = 3, then the substring “abab” is a super-boring substring because it contains a palindrome “aba” whose length is ≥ 3. But the substring “bba” is a valid non super-boring substring. Find the number of substrings which are not super-boring. Two substrings are considered different only if their starting or ending positions are different. Input Specification The first line of input contains an integer T, denoting the number of test cases. The first line of each test cases contains an integer K and the next line contains the string S consisting of lower case English alphabets. Constraints 1 ≤ T ≤ 100 K ≤ |S| ≤ 10 5 Sum of |S| over all test cases <= 10 6 Note: Here |S| denotes the length of the string S. Output Specification For each test case you have to print the number of non super-boring substring of the string S. Statements Input Output 3 3 bababe 4 abcbbcbc 3 aabacecc 12 27 20
題意:
給你一個字串,求區間內不包含長度k以上的迴文串的子串個數
題解:
馬拉車先求出迴文長度,之後每個字元找過去,易證馬拉車的迴文半徑-1就是字串的迴文長度,然後只需要找符合k的最短長度,如果是不同奇偶的話就是+1,那麼在這個字串前面有(i+1)/2-len/2個字元,這些字元就是包括長度至少為k的子串,那麼我們就把他加到樹狀陣列中,然後樹狀陣列記錄的是最大值,就代表以pos為結尾的子串,含有長度為k的迴文串的子串有多少個 舉個例子: 假設有asdfgfzxc這麼一個字串,k=3,很明顯fgf是滿足條件的,那麼在後一個f之後便放到樹狀陣列中4代表從6這個位置開始有4個滿足要求的迴文串,z,x,c這些位置都要減4.
#include<bits/stdc++.h> using namespace std; #define maxn 1000050 #define ll long long char s[maxn]; char ss[2*maxn]; int p[2*maxn]; void manacher(char s[],int len) { int i,j,len1; for(i=0;i<2*len+2;i++)ss[i]='#'; for(i=0;i<len;i++)ss[i*2+2]=s[i]; len1=len*2+1;ss[0]='$'; int mx=0,id=0; int ans=0; for(int i=0;i<len1;i++){ p[i]=mx>i?min(p[2*id-i],mx-i ):1; while(ss[i+p[i] ]==ss[i-p[i] ] )p[i]++; if(ans<p[i])ans=p[i]; if(i+p[i]>mx){ mx=i+p[i]; id=i; } } } int sum[maxn]; int mlen; int lowbit(int x) { return x&(-x); } void add(int pos,int val) { for(int i=pos;i<=mlen;i+=lowbit(i)) sum[i]=max(sum[i],val); } ll query(int pos) { ll ans=0; for(int i=pos;i>=1;i-=lowbit(i)) ans=max(ans,(ll)sum[i]); return ans; } vector<int>vec[500005]; int len[500005]; int main() { int t; scanf("%d",&t); while(t--) { memset(sum,0,sizeof(sum)); int k; scanf("%d",&k); scanf("%s",s); manacher(s,strlen(s)); mlen=strlen(ss); ll ans=0; for(int i=2;i<=mlen;i++) { int len=p[i]-1; if(len<k) continue; if((len+k)%2==0) len=k; else len=k+1; int val=(i+1)/2-len/2; int pos=val+len-1; add(pos,val); } int n=strlen(s); for(int i=1;i<=n;i++) { int num=query(i); ans+=i-num; } printf("%lld\n",ans); } return 0; }