洛谷 P3501 [POI2010]ANT-Antisymmetry 题解

每日一题 day72 打卡

Analysis

这道题一开始我就想到了暴力哈希的做法,但是因为n有 500000 那么大,所以单纯的哈希肯定是不行的。

于是我就上网翻了几篇题解,发现都是二分+哈希,于是思考二分的做法。

之前我就有一个想法,找到所有相邻不一样的点(即本身是反对称的且可能是更大的反对称串的对称轴),再判断其能延伸为多少个反对称串。(时间显然超限)

现在只需二分延伸串的长度的一半(即 l )来实现就好了。

以下为代码实现:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define ull unsigned long long
 6 #define int long long
 7 #define maxn 500010
 8 #define rep(i,s,e) for(register int i=s;i<=e;++i)
 9 #define dwn(i,s,e) for(register int i=s;i>=e;--i)
10 using namespace std;
11 inline int read()
12 {
13     int x=0,f=1;
14     char c=getchar();
15     while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();}
16     while(c>='0'&&c<='9') {x=x*10+c-'0'; c=getchar();}
17     return f*x;
18 }
19 inline void write(int x)
20 {
21     if(x<0){putchar('-');x=-x;}
22     if(x>9)write(x/10);
23     putchar(x%10+'0');
24 }
25 int n,base=13131,ans;
26 char str[maxn],counter_str[maxn];
27 ull power[maxn];
28 struct node 
29 {
30     ull x,y;
31 }hash[maxn];
32 void init()
33 {
34     power[0]=1;
35     rep(i,1,n) power[i]=power[i-1]*base;
36     rep(i,1,n) hash[i].x=hash[i-1].x*base+str[i]-'0';
37     dwn(i,n,1) hash[i].y=hash[i+1].y*base+counter_str[i]-'0';
38 }
39 inline void dich(int x)
40 {
41     int l=0,r=min(x,n-x);
42     while(l<r)
43     {
44         int mid=(l+r+1)>>1;
45         if(hash[x].x-hash[x-mid].x*power[mid]==hash[x+1].y-hash[x+1+mid].y*power[mid]) l=mid;
46         else r=mid-1;
47     }
48     ans+=l;
49 }
50 signed main()
51 {
52     n=read();
53     scanf("%s",str+1);
54     rep(i,1,n)
55     {
56         if(str[i]=='0') counter_str[i]='1';
57         else counter_str[i]='0';
58     }
59     init();    
60     rep(i,1,n)
61         if(str[i]!=str[i+1]) 
62             dich(i);
63     write(ans);
64     return 0;
65 }

如有失误请各位大佬斧正(反正我不认识斧正是什么意思)

原文地址:https://www.cnblogs.com/handsome-zyc/p/12434830.html