字符串的最小表示法,参考了1+学长的博客,自己举了几个例子,简单了理解了一下,但是不够深入,还需要探究
推荐周源03年的论文《浅析“最小表示法”思想在字符串循环同构问题中的应用》
这篇讲的比较清晰,能体会的打循环最小表示法的主要思想


1
int
Minimum_Representation(
char
*
s,
int
len)
2 {
3 int i = 0 , j = 1 , k = 0 , t;
4 while (i < len && j < len && k < len)
5 {
6 t = s[(i + k) % len] - s[(j + k) % len];
7 if (t == 0 ) k ++ ;
8 else
9 {
10 if (t < 0 ) j += k + 1 ;
11 else i += k + 1 ;
12 if (i == j) j ++ ;
13 k = 0 ;
14 }
15 }
16 return min(i, j);
17 }
2 {
3 int i = 0 , j = 1 , k = 0 , t;
4 while (i < len && j < len && k < len)
5 {
6 t = s[(i + k) % len] - s[(j + k) % len];
7 if (t == 0 ) k ++ ;
8 else
9 {
10 if (t < 0 ) j += k + 1 ;
11 else i += k + 1 ;
12 if (i == j) j ++ ;
13 k = 0 ;
14 }
15 }
16 return min(i, j);
17 }
有根树的同构判定参考byvoid牛的blog
http://www.byvoid.com/blog/directed-tree-bracket-sequence/
算法的思想很好理解,写起来也很清晰,简单。
具体思想见下面的注释


1
#include
<
iostream
>
2 #include < vector >
3 #include < string >
4 #include < algorithm >
5 #include < numeric >
6 using namespace std;
7 /* 有根树的最小表示法
8 * 一旦发现depth为0表示发现一颗子树,
9 * 递归维护子树,然后对所有子树排序
10 * 用字典序最下相加构成新的子树返回
11 * 开始把整个树加出入边,一般化处理
12 */
13 string minimum_presatation( string tree)
14 {
15 if (tree == " 01 " )
16 return tree;
17 tree = tree.substr( 1 , tree.size() - 2 );
18 vector < string > subtrees;
19 int depth = 0 ;
20 int root = 0 ,back = 1 ;
21 for ( string ::iterator i = tree.begin(); i != tree.end();i ++ , back ++ )
22 {
23 depth += ( * i) == ' 0 ' ? 1 : - 1 ;
24 if (depth == 0 )
25 {
26 string subtree = minimum_presatation(tree.substr(root, back - root));
27 subtrees.push_back(subtree);
28 root = back;
29 }
30 }
31 sort(subtrees.begin(), subtrees.end());
32 string presatation = "" ;
33 presatation = accumulate(subtrees.begin(), subtrees.end(), string ( "" ));
34 return " 0 " + presatation + " 1 " ;
35 }
36
37 int main()
38 {
39 int cases;
40 cin >> cases;
41 string tree_1, tree_2;
42 while (cases -- )
43 {
44 cin >> tree_1 >> tree_2;
45 tree_1 = " 0 " + tree_1 + " 1 " ;
46 tree_2 = " 0 " + tree_2 + " 1 " ;
47 tree_1 = minimum_presatation(tree_1);
48 tree_2 = minimum_presatation(tree_2);
49 cout << (tree_1 == tree_2 ? " same " : " different " ) << endl;
50 }
51 return 0 ;
52 }
2 #include < vector >
3 #include < string >
4 #include < algorithm >
5 #include < numeric >
6 using namespace std;
7 /* 有根树的最小表示法
8 * 一旦发现depth为0表示发现一颗子树,
9 * 递归维护子树,然后对所有子树排序
10 * 用字典序最下相加构成新的子树返回
11 * 开始把整个树加出入边,一般化处理
12 */
13 string minimum_presatation( string tree)
14 {
15 if (tree == " 01 " )
16 return tree;
17 tree = tree.substr( 1 , tree.size() - 2 );
18 vector < string > subtrees;
19 int depth = 0 ;
20 int root = 0 ,back = 1 ;
21 for ( string ::iterator i = tree.begin(); i != tree.end();i ++ , back ++ )
22 {
23 depth += ( * i) == ' 0 ' ? 1 : - 1 ;
24 if (depth == 0 )
25 {
26 string subtree = minimum_presatation(tree.substr(root, back - root));
27 subtrees.push_back(subtree);
28 root = back;
29 }
30 }
31 sort(subtrees.begin(), subtrees.end());
32 string presatation = "" ;
33 presatation = accumulate(subtrees.begin(), subtrees.end(), string ( "" ));
34 return " 0 " + presatation + " 1 " ;
35 }
36
37 int main()
38 {
39 int cases;
40 cin >> cases;
41 string tree_1, tree_2;
42 while (cases -- )
43 {
44 cin >> tree_1 >> tree_2;
45 tree_1 = " 0 " + tree_1 + " 1 " ;
46 tree_2 = " 0 " + tree_2 + " 1 " ;
47 tree_1 = minimum_presatation(tree_1);
48 tree_2 = minimum_presatation(tree_2);
49 cout << (tree_1 == tree_2 ? " same " : " different " ) << endl;
50 }
51 return 0 ;
52 }