序列自动机两题 51Nod2504 是子序列的个数 CodeForcesEDU81 Obtain The String
序列自动机是用于处理子序列问题的一种工具。其实现类似KMP,大致操作是建立一个Next数组,用于各自操作。
1.
51Nod 2504
给定一个字符串和若干个word,问有多少个word是该字符串的子序列。
注意建立Next时从1开始。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#pragma warning(disable:4996) #include<iostream> #include<algorithm> #include<bitset> #include<tuple> #include<unordered_map> #include<fstream> #include<iomanip> #include<string> #include<cmath> #include<cstring> #include<vector> #include<map> #include<set> #include<list> #include<queue> #include<stack> #include<sstream> #include<cstdio> #include<ctime> #include<cstdlib> #define INF 0x3f3f3f3f #define inf 0x7FFFFFFF #define MOD 998244353 #define moD 1000000003 #define pii pair<int,string> #define eps 1e-8 #define equals(a,b) (fabs(a-b)<eps) #define bug puts("bug") #define re register #define fi first #define se second const int maxn = 5e4 + 5; const double Inf = 10000.0; const double PI = acos(-1.0); typedef long long ll; typedef unsigned long long ull; using namespace std; int Next[maxn][30]; char s[maxn]; char word[55]; int main() { scanf("%s", s + 1); int T; scanf("%d", &T); int n = strlen(s + 1); for (int i = n ;i; i--) { for (int j = 0; j < 26; j++) Next[i - 1][j] = Next[i][j]; Next[i- 1][s[i] - 'a'] = i; } int cnt = 0; while (T--) { scanf("%s", word); int l = strlen(word); int count = 0; int j = 0; for (int i = 0; i < l; i++) if (Next[j][word[i] - 'a']) j = Next[j][word[i] - 'a'], count++; if (count == l) cnt++; } printf("%d", cnt); }
2.
Obtain the String
从一个空串要求变到字符串 t 。 变换规则是从a串中每次找一个子串添加到“空串”的末尾。
问最少的操作次数。
贪心的匹配子串即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#pragma warning(disable:4996) #include<iostream> #include<algorithm> #include<bitset> #include<tuple> #include<unordered_map> #include<fstream> #include<iomanip> #include<string> #include<cmath> #include<cstring> #include<vector> #include<map> #include<set> #include<list> #include<queue> #include<stack> #include<sstream> #include<cstdio> #include<ctime> #include<cstdlib> #define INF 0x3f3f3f3f #define inf 0x7FFFFFFF #define MOD 998244353 #define moD 1000000003 #define pii pair<int,string> #define eps 1e-8 #define equals(a,b) (fabs(a-b)<eps) #define bug puts("bug") #define re register #define fi first #define se second const int maxn = 1e5 + 5; const double Inf = 10000.0; const double PI = acos(-1.0); typedef long long ll; typedef unsigned long long ull; using namespace std; int Next[maxn][30]; char s[maxn]; char word[maxn]; int main() { int T; scanf("%d", &T); while (T--) { memset(Next, 0, sizeof Next); scanf("%s %s", s + 1, word); int n = strlen(s + 1); int len = strlen(word); for (int i = n; i; i--) { for (int j = 0; j < 26; j++) Next[i - 1][j] = Next[i][j]; Next[i - 1][s[i] - 'a'] = i; } int res = 0; int cnt = len; int last = 0; int f = 1; while (cnt) { res++; int j = 0; int tmp = last; for (int i = last; i < len; i++) { if (Next[j][word[i] - 'a']) j = Next[j][word[i] - 'a'], tmp++, cnt--; else break; } if (tmp == last) { puts("-1"); f = 0; break; } last = tmp; } if (f) printf("%d\n", res); } }