题目链接:http://poj.org/problem?id=3167
题意:模式串可以浮动的模式匹配问题给出模式串的相对大小,需要找出模式串匹配次数和位置。
思路:统计比当前数小,和于当前数相等的,然后进行kmp。
比如说模式串:1,4,4,2,3,1 而主串:5,6,2,10,10,7,3,2,9,那么2,10,10,7,3,2就是匹配的
code:
1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 using namespace std; 5 const int MAXN = 100005; 6 const int MAXM = 25005; 7 8 int a[MAXN]; // 存放主串 9 int b[MAXM]; // 存放模式串 10 int as[MAXN][30]; // as[i][j] = k表示0 - i位中有k个数字j 11 int bs[MAXM][30]; // bs[i][j] = k表示0 - i位中有k个数字j 12 int next[MAXM]; // 存放模式串失配时的移动位数 13 vector<int> ans; // 存放结果 14 int n, m, s; 15 16 void Init() 17 { 18 ans.clear(); 19 memset(as, 0, sizeof(as)); 20 memset(bs, 0, sizeof(bs)); 21 as[1][a[1]] = 1; 22 bs[1][b[1]] = 1; 23 for (int i = 2; i <= n; ++i) 24 { 25 memcpy(as[i], as[i - 1], sizeof(as[0])); 26 ++as[i][a[i]]; 27 } 28 for (int i = 2; i <= m; ++i) 29 { 30 memcpy(bs[i], bs[i - 1], sizeof(bs[0])); 31 ++bs[i][b[i]]; 32 } 33 } 34 35 void GetNext() 36 { 37 memset(next, 0, sizeof(next)); 38 int i = 1, j = 0, k = 0; 39 next[1] = 0; 40 while (i <= m) 41 { 42 int si = 0, sj = 0, ei = 0, ej = 0; 43 for (k = 1; k < b[i]; ++k) 44 si += bs[i][k] - bs[i - j][k]; 45 ei = bs[i][k] - bs[i - j][k]; 46 for (k = 1; k < b[j]; ++k) 47 sj += bs[j][k]; 48 ej = bs[j][k]; 49 if (0 == j || (si == sj && ei == ej)) next[++i] = ++j; 50 else j = next[j]; 51 } 52 } 53 54 void Kmp() 55 { 56 int i = 1, j = 1, k = 1; 57 while (i <= n) 58 { 59 int si = 0, sj = 0, ei = 0, ej = 0; 60 for (k = 1; k < a[i]; ++k) 61 si += as[i][k] - as[i - j][k]; 62 ei = as[i][k] - as[i - j][k]; 63 for (k = 1; k < b[j]; ++k) 64 sj += bs[j][k]; 65 ej = bs[j][k]; 66 if (0 == j || (si == sj && ei == ej)) ++i, ++j; 67 else j = next[j]; 68 if (j == m + 1) 69 { 70 ans.push_back(i - m); 71 j = next[j]; 72 } 73 } 74 } 75 76 int main() 77 { 78 while (scanf("%d %d %d", &n, &m, &s) == 3) 79 { 80 for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); 81 for (int i = 1; i <= m; ++i) scanf("%d", &b[i]); 82 Init(); 83 GetNext(); 84 Kmp(); 85 size_t len = ans.size(); 86 printf("%d\n", len); 87 for (size_t i = 0; i < len; ++i) printf("%d\n", ans[i]); 88 } 89 return 0; 90 }
时间: 2024-10-09 23:30:09