题意:
给你两个串s和t,其中t是由s中选择若干个不相交的区间翻转得到的,现在要求求出最少的翻转次数以及给出方案。
1≤|s|=|t|≤500000
题解:
我们将两个字符串合成成T=s1t1s2t2...sntn T=s1t1s2t2...sntn
那么问题就是最少要把整个字符串T 拆分成若干个偶数长度(并且长度大于2)的回文串。
长度是2的表示没有反转。
然后就变成了最小回文分解模型 ,然后直接上板子。
最小回文分解 论文在此
1 #include <set> 2 #include <map> 3 #include <stack> 4 #include <queue> 5 #include <cmath> 6 #include <ctime> 7 #include <cstdio> 8 #include <string> 9 #include <vector> 10 #include <cstring> 11 #include <iostream> 12 #include <algorithm> 13 #include <unordered_map> 14 15 #define pi acos(-1.0) 16 #define eps 1e-9 17 #define fi first 18 #define se second 19 #define rtl rt<<1 20 #define rtr rt<<1|1 21 #define bug printf("******\n") 22 #define mem(a, b) memset(a,b,sizeof(a)) 23 #define name2str(x) #x 24 #define fuck(x) cout<<#x" = "<<x<<endl 25 #define sfi(a) scanf("%d", &a) 26 #define sffi(a, b) scanf("%d %d", &a, &b) 27 #define sfffi(a, b, c) scanf("%d %d %d", &a, &b, &c) 28 #define sffffi(a, b, c, d) scanf("%d %d %d %d", &a, &b, &c, &d) 29 #define sfL(a) scanf("%lld", &a) 30 #define sffL(a, b) scanf("%lld %lld", &a, &b) 31 #define sfffL(a, b, c) scanf("%lld %lld %lld", &a, &b, &c) 32 #define sffffL(a, b, c, d) scanf("%lld %lld %lld %lld", &a, &b, &c, &d) 33 #define sfs(a) scanf("%s", a) 34 #define sffs(a, b) scanf("%s %s", a, b) 35 #define sfffs(a, b, c) scanf("%s %s %s", a, b, c) 36 #define sffffs(a, b, c, d) scanf("%s %s %s %s", a, b,c, d) 37 #define FIN freopen("../in.txt","r",stdin) 38 #define gcd(a, b) __gcd(a,b) 39 #define lowbit(x) x&-x 40 #define IO iOS::sync_with_stdio(false) 41 42 43 using namespace std; 44 typedef long long LL; 45 typedef unsigned long long ULL; 46 const ULL seed = 13331; 47 const LL INFLL = 0x3f3f3f3f3f3f3f3fLL; 48 const int maxn = 1e6 + 7; 49 const int maxm = 8e6 + 10; 50 const int INF = 0x3f3f3f3f; 51 const int mod = 1e9 + 7; 52 //最小回文分解 53 //根据题目需求求出分解成怎样的回文串 54 //本代码用于将串分解成最小数目的长度偶数回文的方案数 55 char s[maxn], s1[maxn], s2[maxn]; 56 57 struct Palindrome_Automaton { 58 int len[maxn], next[maxn][26], fail[maxn], cnt[maxn]; 59 int num[maxn], S[maxn], sz, n, last; 60 int diff[maxn];//表示相邻回文后缀的等差; 61 int slk[maxn];//表示上一个等差数列的末项 62 int fp[maxn]; 63 64 int newnode(int l) { 65 for (int i = 0; i < 26; ++i)next[sz][i] = 0; 66 cnt[sz] = num[sz] = 0, len[sz] = l; 67 return sz++; 68 } 69 70 void init() { 71 sz = n = last = 0; 72 newnode(0); 73 newnode(-1); 74 S[0] = -1; 75 fail[0] = 1; 76 } 77 78 int get_fail(int x) { 79 while (S[n - len[x] - 1] != S[n])x = fail[x]; 80 return x; 81 } 82 83 void add(int c, int pos) { 84 c -= ‘a‘; 85 S[++n] = c; 86 int cur = get_fail(last); 87 if (!next[cur][c]) { 88 int now = newnode(len[cur] + 2); 89 fail[now] = next[get_fail(fail[cur])][c]; 90 next[cur][c] = now; 91 num[now] = num[fail[now]] + 1; 92 diff[now] = len[now] - len[fail[now]]; 93 slk[now] = (diff[now] == diff[fail[now]] ? slk[fail[now]] : fail[now]); 94 } 95 last = next[cur][c]; 96 cnt[last]++; 97 } 98 99 //dp[i]表示s[1...i] s[1...i]s[1...i]的最少反转次数。 100 //pre[i] pre[i]pre[i]表示在最优解里面i为区间右端点的左端点下标。 101 void solve(int n, int *dp, int *pre) { 102 for (int i = 0; i <= n; i++) dp[i] = INF, pre[i] = 0; 103 init(); 104 dp[0] = 0, fp[0] = 1; 105 for (int i = 1; i <= n; i++) { 106 add(s[i], i); 107 for (int j = last; j; j = slk[j]) { 108 fp[j] = i - len[slk[j]] - diff[j]; 109 if (diff[j] == diff[fail[j]] && dp[fp[j]] > dp[fp[fail[j]]]) fp[j] = fp[fail[j]]; 110 if (i % 2 == 0 && dp[i] > dp[fp[j]] + 1) {//分解成 长度为偶数的回文串 111 dp[i] = dp[fp[j]] + 1; 112 pre[i] = fp[j]; 113 } 114 } 115 if (i % 2 == 0 && s[i] == s[i - 1] && dp[i] >= dp[i - 2]) {//长度是2的表示没有反转 116 dp[i] = dp[i - 2]; 117 pre[i] = i - 2; 118 } 119 } 120 } 121 } pam; 122 123 int dp[maxn], pre[maxn]; 124 125 int main() { 126 // FIN; 127 sffs(s1 + 1, s2 + 1); 128 int n = 2 * strlen(s1 + 1), len1 = 0, len2 = 0; 129 for (int i = 1; i <= 2 * n; i++) { 130 if (i & 1) s[i] = s1[++len1]; 131 else s[i] = s2[++len2]; 132 } 133 // fuck(s + 1); 134 pam.solve(n, dp, pre); 135 if (dp[n] > n) return 0 * printf("-1\n"); 136 else printf("%d\n", dp[n]); 137 for (int i = n; i; i = pre[i]) 138 if (i - pre[i] > 2) printf("%d %d\n", pre[i] / 2 + 1, i / 2); 139 return 0; 140 }
原文地址:https://www.cnblogs.com/qldabiaoge/p/11403882.html
时间: 2024-10-14 19:52:08