下標 i :0 是$ , 原字串插入#字元變為 奇數長度,結尾位置新增@ 維持奇數字元個數
arr字串:經過處理的字串 , eg -> fabbac 「$ # f # a # b # b # a # c # @」
輔助陣列p:p[i] 表示 arr字串 在 i 位置的最長回文半徑
兩個關係:
最長回文串(是原串"fabbac"的最長回文串長度) = p[i] - 1;
以 i 為中心的 回文串( arr串 ) 起始位置(索引) = ( i - p[i] ) / 2;
知道這些,再看**就能秒懂了。
板子:
#include #include #include #include #include #include #include #include #include #include #include #include #define clear( x , y ) memset( x , y , sizeof(x) );
#define qcin() std::ios::sync_with_stdio(false);
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 7;
const int inf = 1e9 + 7;
int n , m;
char s[maxn] , t[maxn];
int manacher()
// 第一步:預處理,將原字串轉換為新字串
int n = -1;
t[++n] = '$';
for (int i = 0 ; i < lens ; i++)
t[++n] = '#' , t[++n] = '@';
++n;
// 第二步:計算陣列p、起始索引、最長回文半徑
int p[n];
int id = 0, mx = 0;
int maxlength = -1;
int index = 0;
for (int j=1; jj ? min(p[2*id-j], mx-j) : 1;
// 向左右兩邊延伸,擴充套件右邊界
while (t[j+p[j]] == t[j-p[j]])
// 如果回文子串的右邊界超過了mx,則需要更新mx和id的值
if (mx < p[j] + j)
// 如果回文子串的長度大於maxlength,則更新maxlength和index的值
if (maxlength < p[j] - 1)
}return maxlength;
}int main()
套用ac自動機思想,建立兩顆樹
0樹 和 1樹 , 前者表示偶數回文串,後者表示奇數回文串
通過fail指標操作可以在兩棵樹中 來回跳躍
具體內容 就看**解釋,可以很好地理解
主要是要知道
還有一些點需要了解
我們計算給出的s串的 所有回文子串(包括重複的)的數目,有兩種方法
第一種是用count函式,但是計算的時候0樹 和1樹 的cnt被重複計算了,所以只算乙個就行。
void count()
}
在for(1 ~ lens)的過程中 把每次的 num[last] 加到乙個sum中即可。思考一下,這個方法不僅是計算所有回文子串數目的方法,也是計算 已插入字符集(可以是1 ~ i 或 n ~ i) 的回文子串數目——包括重複部分(再強調一下)。
//sum[lens] 就是全部回文子串的數目
sum[0] = 0;
for(int i = 1 ; i <= lens ; ++i)
//_________________________________
//sum[1]也是全部回文子串的數目
sum[lens+1] = 0;
for(int i = lens ; i >= 1 ; --i)
當這個模板處理字串過長時可能會mle,這時候就需要一些處理,或者直接考慮放棄此演算法,改用manacher了,因為我們改用鍊錶模擬時,如果要處理的字串中字元範圍是100,很可能會tle,當然只有大小寫字母是能滿足的。
用下面第乙個模板1 在2e6 * 26時就會mle , 改用模板2 可過,當然速度稍慢一些,畢竟常數大了點。
const int maxn = 5e5 + 7;
const int inf = 1e9 + 7;
const int over = 26;
int n , m;
struct plt
void init()
int get_fail(int x)
void add(int c)
last = nxt[cur][c];
cnt[last]++; }
void count()
} void buildtree()
} void solve()
};
#include #include #include #include #include #include #include #include #include #include #include #include #define clear( x , y ) memset( x , y , sizeof(x) );
#define qcin() std::ios::sync_with_stdio(false);
using namespace std;
typedef long long ll;
const int maxn = 2e6 + 7;
const int inf = 1e9 + 7;
const int over = 26;
const ll mod = 51123987;
int n , m;
struct link //next的鄰接表
void clear(int x)
int get(int x,int y)
return 0;
}void insert(int x,int y,int z)
};struct plt
void init()
void input()
int get_fail(int x)
void add(int x)
cnt[last]++;
} void buildtree()
} void count()
} void solve()
};int main()
洛谷 4555
洛谷1659
(下面的 密碼:rushb)
hysbz - 3676
ural - 1960
uvalive - 7041
codeforces - 17e
hdu - 3948
回文樹(回文自動機) 筆記
回文樹詳解1 what is palindromic auto machine?回文自動機,又叫回文樹,是由俄羅斯人 mikhailrubinchik於2014年夏發明的 這是一種比較新的資料結構,在原文中已有詳細介紹與 實現。回文樹其實不是嚴格的樹形結構,因為它有是兩棵樹,分別是偶數長度的回文樹和...
最長回文 馬拉車演算法
總時間限制 10000ms 單個測試點時間限制 1000ms 記憶體限制 5120000kb描述 給出乙個只由小寫英文本元a,b,c.y,z組成的字串s,求s中最長回文串的長度.回文就是正反讀都是一樣的字串,如aba,abba等 輸入乙個檔案一組資料 每組輸入為一行小寫英文本元a,b,c.y,z組成...
回文自動機
回文自動機,又叫回文樹,是由俄羅斯人 mikhailrubinchik於2014年夏發明的 這是一種比較新的資料結構,在原文中已有詳細介紹與 實現。回文樹其實不是嚴格的樹形結構,因為它有是兩棵樹,分別是偶數長度的回文樹和奇數長度的回文樹,樹中每個節點代表乙個回文串。為了方便,第一棵樹的根是乙個長度為...