KMP && Extended KMP:
字串a0,a1,a2,a3,a4...an
------------------------------------------------------------------------------
KMP:
记录fail[i]记录假如i+1匹配失败应该退回到哪里。。。
同时也表示了a(i-fail[i]+1)..ai与a0,a1...a(fail[i])匹配。即字串后缀与前缀的匹配。
假如fail[10]=5
a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10
a5 a6 a7 a8 a9 a10
那么当我们匹配 ci!=a11时 我们就没有必要重新开始只需从a5开始因为
a5 a6 a7 a8 a9 a10与a1 a2 a3 a4 a5已经匹配
-------------------------------------------------------------------------------
Extended KMP:
记录一个la[i]长度数组。表示从i开始字串的前缀和字串前缀能够匹配的最大长度。
a0...a(la[i]-1) 与 ai...a(la[i]+i-1) 匹配
做法:
先预处理出la[0]和la[1]; 令 k=1
a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10
ck ck+1 ck+2 ck+3 ck+4 ck+5 ck+6ck+7 ck+8 ck+9 ck+10
当前做i时,前i-1的la值都是求好的
假设i=ck+t
那么la[i]的计算就可以用上la[i-k]即la[t]的值!!
(显然ck+t..c(xx) 已经和 a(t)..a(xx)匹配了!!!所以la[t]的值就可以用在la[k+t]上!)
假如k的匹配长度为len,而i+la[t]-1仍旧小于len ,那么la[i]就就只能等于la[t];
如果 i+la[t]-1 大于len ,那么就需要继续向下匹配到不能够匹配,
更新k值
----------------------------------------------------------------------------------
两个算法的优化之处都是把之前计算过的有用值记录下来。从而避免重复计算提高效率
-----------------------------------------------------------------------------------
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3298
题目给出模式串A,匹配串B,求A在B中的匹配长度。注意这里的A可以旋转。
1 3 2
2 3 2 1 3 2 1 5
在这里 3 2 1 3 2 1 可以被 1 3 2 匹配。
我们发现到这样一个串一定可以被分成三个部分
3 2 1 3 2 1 5
第一部分 是A串的后缀。第二部分是若干个A串。第三部分是A的前缀。
注意到第一部分同时是自己这个串的后缀。第三部分同时自己这个串的前缀。
注意到上面红字部分。这是我们显然要选择Extended KMP
我们只要对AB做一次Extended KMP。就可以完成第三部分。
将AB串倒过来再做一次Extended KMP。可以完成第一部分。
剩余的就是一遍扫描就可以了。


#include < cstdio >
using namespace std;
int a[ 1001 ],b[ 1000001 ];
int la[ 1000001 ],pl[ 1000001 ],pr[ 1000001 ];
int n,m,tot,ans,len,l,k,j,t,now;
void swap( int & a, int & b)
{
t = a;a = b;b = t;
}
int solve()
{
la[ 0 ] = n;
j = 0 ;
while (j < n - 1 && a[j + 1 ] == a[j]) ++ j;
la[ 1 ] = j;k = 1 ;
for ( int i = 2 ;i < n; ++ i)
{
len = k + la[k] - 1 ;l = la[i - k];
if (i + l - 1 < len) la[i] = l;
else
{
j = 0 ;
if (len - i + 1 > j) j = len - i + 1 ;
while (i + j < n && a[i + j] == a[j]) ++ j;
la[i] = j;k = i;
}
}
j = 0 ;
while (j < n && j < m && a[j] == b[j]) ++ j;
pl[ 0 ] = j;k = 0 ;
for ( int i = 1 ;i < m; ++ i)
{
len = k + pl[k] - 1 ;l = la[i - k];
if (i + l - 1 < len) pl[i] = l;
else
{
j = 0 ;
if (len - i + 1 > j) j = len - i + 1 ;
while (i + j < m && j < n && b[i + j] == a[j]) ++ j;
pl[i] = j;k = i;
}
}
}
int main()
{
freopen( " 3298.in " , " r " ,stdin);
freopen( " 3298.out " , " w " ,stdout);
while (cin >> n >> m)
{
ans = 0 ;
for ( int i = 0 ;i < n; ++ i) scanf( " %d " , & a[i]);
for ( int i = 0 ;i < m; ++ i) scanf( " %d " , & b[i]);
solve();
for ( int i = 0 ;i < m; ++ i) pr[i] = pl[i];
for ( int i = 0 ;i < n / 2 ; ++ i) swap(a[i],a[n - i - 1 ]);
for ( int i = 0 ;i < m / 2 ; ++ i) swap(b[i],b[m - i - 1 ]);
solve();
for ( int i = 0 ;i < m / 2 ; ++ i) swap(pl[i],pl[m - 1 - i]);
for ( int i = 0 ;i < m; ++ i)
{
if ( (i - n < 0 || pr[i - n] != n ) && pr[i] == n)
{
now = i;
while (now < m && pr[now] == n) now += n;
tot = now - i;
if (now < m) tot += pr[now];
if (i >= 1 ) tot += pl[i - 1 ];
if (tot > ans) ans = tot;
}
}
if (ans == 0 ) cout << " bad " << endl; else
cout << ans << endl;
}
return 0 ;
}
------------------------------------------------------------------------------------
http://61.187.179.132:8080/JudgeOnline/showproblem?problem_id=1100
表示被2了- -!用cin是自寻死路啊!!!
用scanf读入%lf也是自寻死路!!!
algorithm:
1、将图转化成2*n个特征,边+角度。(很NB的,感觉很难想到!!!)
2、类似上面的方法就可以做出来了。
这数据很2啊,外国人出的数据果断厉害。
我点积算完cos值再acos回去算出0~2*pi的值居然跟距离冲突了,wa一个点。
算完cos值保留下来以0~2的值AC~
数据太强大,scanf读入花了大多数时间。要读int才可能过= =!
--------------------------------------------------------------------------------------


2 #include < cstdio >
3 #include < cmath >
4 #define LL long long
5 #define N 1000001
6 #define PI 3.141592653
7 using namespace std;
8 struct node{
9 double x,y;
10 } a[N];
11
12 LL ans,T,n,j,k,L,l;
13 int aa,bb;
14 double b[N],c[N],x1,y11,x2,y2,tt;
15 LL pl[N],pr[N],len[N];
16
17 double dis(node a,node b)
18 {
19 return sqrt( (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) );
20 }
21 double angle(node a,node b,node c)
22 {
23 x1 = a.x - b.x;y11 = a.y - b.y;x2 = c.x - b.x;y2 = c.y - b.y;
24 tt = (x1 * x2 + y11 * y2) / dis(a,b) / dis(b,c);
25 if (x1 * y2 - x2 * y11 > 0 ) return tt;
26 else return 1 + tt;
27 }
28 bool same( double x, double y)
29 {
30 return abs(x - y) < 1e - 6 ;
31 }
32 void Ex_Pre_KMP()
33 {
34 len[ 0 ] = 2 * n;
35 j = 0 ;
36 while (j < 2 * n - 1 && same(b[j],b[j + 1 ]) ) ++ j;
37 len[ 1 ] = j;k = 1 ;
38 for (LL i = 2 ;i < 2 * n; ++ i)
39 {
40 L = k + len[k] - 1 ;l = len[i - k];
41 if (i + l - 1 < L) len[i] = l;
42 else
43 {
44 j = 0 ;
45 if (L - i + 1 > j) j = L - i + 1 ;
46 while (i + j < 2 * n && same(b[i + j],b[j]) ) ++ j;
47 len[i] = j;k = i;
48 }
49 }
50 }
51 void Ex_KMP()
52 {
53 j = 0 ;
54 while (j < 2 * n && same(b[j],c[j]) ) ++ j;
55 pl[ 0 ] = j;k = 0 ;
56 for (LL i = 1 ;i < 2 * n; ++ i)
57 {
58 L = k + pl[k] - 1 ;l = len[i - k];
59 if (i + l - 1 < L) pl[i] = l;
60 else
61 {
62 j = 0 ;
63 if (L - i + 1 > j) j = L - i + 1 ;
64 while (i + j < 2 * n && same(c[i + j],b[j]) ) ++ j;
65 pl[i] = j;k = i;
66 }
67 }
68 }
69 int main()
70 {
71 freopen( " 1100.in " , " r " ,stdin);
72 freopen( " 1100.out " , " w " ,stdout);
73 cin >> T;
74 for (LL ii = 1 ;ii <= T; ++ ii)
75 {
76 cin >> n;
77 for (LL i = 0 ;i < n; ++ i)
78 {
79 scanf( " %d %d " , & aa, & bb);
80 a[i].x = aa;a[i].y = bb;
81 }
82
83 for (LL i = 0 ;i < n; ++ i)
84 {
85 b[i * 2 ] = dis(a[i],a[ (i + 1 ) % n ]);
86 b[i * 2 + 1 ] = angle(a[ i % n],a[(i + 1 ) % n],a[(i + 2 ) % n] );
87 }
88
89 Ex_Pre_KMP();
90 for (LL i = 0 ;i < 2 * n; ++ i) c[i] = b[ 2 * n - 1 - i];
91 Ex_KMP();
92 for (LL i = 0 ;i < 2 * n; ++ i) pr[ 2 * n - 1 - i] = pl[i];
93
94 for (LL i = 0 ;i < n; ++ i) tt = b[i],b[i] = b[ 2 * n - 1 - i],b[ 2 * n - 1 - i] = tt;
95 for (LL i = 0 ;i < n; ++ i) tt = c[i],c[i] = c[ 2 * n - 1 - i],c[ 2 * n - 1 - i] = tt;
96 Ex_Pre_KMP();
97 Ex_KMP();
98
99
100 ans = 0 ;
101 LL lenn;
102 for (LL i = 0 ;i < n; ++ i)
103 {
104 j = 2 * i;
105 lenn = j + 1 ;
106 if (pr[j] < lenn / 2 ) continue ;
107
108 j = j + 1 ;
109 lenn = 2 * n - 1 - j + 1 ;
110 if (pl[j] < lenn / 2 ) continue ;
111 ++ ans;
112 // cout<<i<<endl;
113 }
114
115 cout << ans << endl;
116 }
117 return 0 ;
118 }
119