[模板] manacher(教程)
还是不会马拉车啊.今天又学了一遍,在这里讲一下.
其实就是一个很妙的思路,就是设置一个辅助的数组len,记录每个点的最大对称长度,然后再存一个mx记录最大的对称子串的右端点.先开二倍数组,然后一点点扩大.有两种情况,一种i比mx大,这种只好暴力匹配了.还有一种就是i<mx,然后比较mx-i和len[2*po - i](po就是mx的对称中心),假如mx>i,那么说明无法再扩展,len[i] = len[2 * po - i];否则还需要暴力匹配.假如不好想,自己画个图就行了.
这里还有一个更负责的教程:
https://www.cnblogs.com/z360/p/6375514.html
大家可以对照看一看.
代码:
#include<iostream> #include<cstdio> #include<cmath> #include<ctime> #include<queue> #include<algorithm> #include<cstring> using namespace std; #define duke(i,a,n) for(register int i = a;i <= n;i++) #define lv(i,a,n) for(register int i = a;i >= n;i--) #define clean(a) memset(a,0,sizeof(a)) const int INF = 1 << 30; typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } char s1[11000002]; char s[22000002]; int len[22000002]; int l = 0; int po = 0; int maxr = 0; int main() { scanf("%s",s1 + 1); l = strlen(s1 + 1); s[0] = '@'; duke(i,1,2 * l + 1) { if(i % 2 == 1) s[i] = '*'; else s[i] = s1[i / 2]; } /*duke(i,0,2 * l + 1) printf("%c ",s[i]); puts("");*/ int mx = -1,ans = 0,po = 0; duke(i,1,2 * l + 1) { if(mx > i) len[i] = min(mx - i,len[2 * po - i]); else len[i] = 1; while(s[i - len[i]] == s[i + len[i]]) len[i]++; if(len[i] + i > mx) { mx = len[i] + i; po = i; } ans = max(ans,len[i] - 1); } printf("%d\n",ans); return 0; }
只想找一个不会伤害我的人