lca求公共祖先,一般使用倍增法
1 vector<int>son[N]; 2 int fa[N][35]; 3 int n, m; 4 int dep[N]; 5 void dfs(int x, int pre){ 6 fa[x][0] = pre; 7 dep[x] = dep[pre] + 1; 8 for (int i = 1; (1 << i) <= n; ++i){ 9 fa[x][i] = fa[fa[x][i - 1]][i-1]; 10 } 11 for (int a : son[x]){ 12 if (a!=pre) 13 dfs(a, x); 14 } 15 } 16 int up(int x, int step){ 17 int ret = x; 18 for (int i = 0; (1 << i) <= n; ++i){ 19 if (((1 << i)&step)!= 0){ 20 ret = fa[ret][i]; 21 } 22 } 23 return ret; 24 } 25 int lca(int x, int y){ 26 if (dep[x]<dep[y]){ 27 swap(x, y); 28 } 29 x = up(x, dep[x] - dep[y]); 30 if (x == y) 31 return x; 32 for (int i = 30; i >= 0; --i){ 33 if (fa[x][i] != fa[y][i]){ 34 x = fa[x][i]; 35 y = fa[y][i]; 36 } 37 } 38 return fa[x][0]; 39 } 40 int main(){ 41 int s; 42 cin >> n >>m>>s; 43 for (int i = 0; i < n - 1; ++i){ 44 int a, b; 45 cin >> a >> b; 46 son[a].push_back(b); 47 son[b].push_back(a); 48 } 49 dfs(s,0);//无根树会因为取不同的根节点祖先会发生改变 50 while (m--){ 51 int a, b; 52 cin >> a >> b; 53 cout << lca(a, b) << endl; 54 } 55 return 0; 56 }//倍增法求lca
kmp一种快速匹配字符串的方式,一般不会用,我们一般会用他的nextarr数组去求解问题
1 int nextarr[N]; 2 void getnext(string s){ 3 memset(nextarr, -1, sizeof(nextarr)); 4 nextarr[1] = 0; 5 int i = 2; 6 int dex = 0; 7 int len = s.size(); 8 while (i <=len){ 9 if (s[dex] == s[i - 1]){ 10 nextarr[i++] = ++dex; 11 } 12 else if (dex>0){ 13 dex = nextarr[dex]; 14 } 15 else 16 nextarr[i++] = 0; 17 } 18 } 19 int kmp(string s1, string s2){ 20 if (s1.empty() || s2.empty() || s1.size() < s2.size()) 21 return -1; 22 int len1 = s1.size(); 23 int len2 = s2.size(); 24 int i1 = 0; 25 int i2 = 0; 26 while (i1 < len1&&i2 < len2){ 27 if (s1[i1] == s2[i2]){ 28 i1++; 29 i2++; 30 } 31 else if (i2 == 0) 32 i1++; 33 else 34 i2 = nextarr[i2]; 35 } 36 return i2 == len2 ? i1 - i2 : -1; 37 }
浙公网安备 33010602011771号