字符串的最小表示法与有根树同构的判定

本文介绍了字符串和有根树的最小表示法的概念及其实现算法,并提供了具体的代码示例。对于字符串,通过循环找到其最小表示形式;而对于有根树,则采用递归方式构造子树并进行排序来得到其最小表示形式。

字符串的最小表示法,参考了1+学长的博客,自己举了几个例子,简单了理解了一下,但是不够深入,还需要探究

推荐周源03年的论文《浅析“最小表示法”思想在字符串循环同构问题中的应用》

这篇讲的比较清晰,能体会的打循环最小表示法的主要思想

ContractedBlock.gif ExpandedBlockStart.gif 字符串最小表示法

   
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 }

有根树的同构判定参考byvoid牛的blog

http://www.byvoid.com/blog/directed-tree-bracket-sequence/

算法的思想很好理解,写起来也很清晰,简单。

具体思想见下面的注释

ContractedBlock.gif ExpandedBlockStart.gif HOJ 1292

   
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 }

转载于:https://www.cnblogs.com/ronaflx/archive/2011/04/04/2005140.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值