[编程珠玑]马尔科夫链自动产生文本

首先是letter-level的马尔科夫链

然后是word-level的马尔科夫链

word-level
  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 
  5 //输入的字符串
  6 char inputchars[4300000];
  7 #define MAXWORDS 80000
  8 //字符串中没一个单词
  9 char *word[MAXWORDS];
 10 //单词个数
 11 int nword=0;
 12 //k-order
 13 int k=2;
 14 
 15 //hash table,bin[i]存储hash到该位置的第一个word索引j,next[j]存储下一个word索引
 16 int next[MAXWORDS];
 17 #define NHASH 49979
 18 int bin[NHASH];
 19 #define MULT 31
 20 
 21 
 22 //以k个单词为单位,进行hash
 23 unsigned int hash(char* str)
 24 {
 25     int n;
 26     unsigned int h=0;
 27     unsigned char* p=str;
 28     for(n=k;n>0;++p)
 29     {
 30         h=MULT*h+*p;
 31         if(*p=='\0')
 32             --n;
 33     }
 34     return h%NHASH;
 35 }
 36 
 37 
 38 //比较前k个单词的大小
 39 int wordncmp(char* p,char *q)
 40 {
 41     int n;
 42     for(n=k;*p==*q;++p,++q)
 43     {
 44         if(*p=='\0'&&(--n)==0)
 45             return 0;
 46     }
 47     return *p-*q;
 48 }
 49 
 50 //从当前单词出发,跳过前n个单词
 51 char* skip(char* p,int n)
 52 {
 53     for(;n>0;++p)
 54     {
 55         if(*p=='\0')
 56             --n;
 57     }
 58     return p;
 59 }
 60 
 61 int main()
 62 {
 63     int i,j,wordsleft,psofar;
 64     char *phrase,*p;
 65     word[0]=inputchars;
 66     //输入字符串,并将每个单词保存到word中,每个单词以'\0'结尾
 67     while((scanf("%s",word[nword]))!=EOF)
 68     {
 69         word[nword+1]=word[nword]+strlen(word[nword])+1;
 70         ++nword;
 71     }
 72     //将最后一个单词的后一个的k个字符设置为\0,保证wordncmp()正确
 73     for(i=0;i<k;++i)
 74         word[nword][i]='\0';
 75 
 76     //初始化hash table
 77     for(i=0;i<NHASH;++i)
 78         bin[i]=-1;
 79 
 80     //构建hash table
 81     for(i=0;i<=nword-k;++i)
 82     {
 83         j=hash(word[i]);
 84         next[i]=bin[j];
 85         bin[j]=i;
 86     }
 87 
 88     //词组先初始化为字符串开始
 89     phrase=inputchars;
 90     //预备输出wordsleft个单词
 91     for(wordsleft=10000;wordsleft>0;--wordsleft)
 92     {
 93         //初始化随机取模的值
 94         psofar=0;        
 95         //对phrase hash后的的列表进行遍历,随机取得一个符合要求的单词
 96         for(j=bin[hash(phrase)];j>=0;j=next[j])
 97             if(wordncmp(phrase,word[j])==0&&rand()%(++psofar)==0)
 98                 p=word[j];
 99         //将phrase重新设置
100         phrase=skip(p,1);
101         //输出符合要求单词的后面第k个单词
102         if(strlen(skip(phrase,k-1))==0)
103             break;
104         printf("%s\n",skip(phrase,k-1));
105     }
106     return 0;    
107 }

 

 

letter-level
 1 //markov:letter-level
 2 
 3 #include <stdio.h>
 4 #include <string.h>
 5 #include <stdlib.h>
 6 
 7 char str[3000000];//保存将要学习的字符串
 8 
 9 int main()
10 {
11     char *p,*q,*nextp;
12     char c;
13     int n=0,k=5/*k-order*/,maxletter,qsofar,i;
14     //输入字符串,末尾输入结束符
15     while((c=getchar())!=EOF)
16         str[n++]=c;
17     str[n]='\0';
18 
19     //初始化先指向字符串开始处
20     p=str;
21 
22     //预备输出maxletter个字符
23     for(maxletter=2000;maxletter>0;--maxletter)
24     {
25         //随机数取模
26         qsofar=0;
27         //从字符串开始到最少还剩k个字符处遍历
28         for(q=str;q<=str+n-k+1;++q)
29         {
30             for(i=0;i<k&&*(p+i)==*(q+i);++i)
31                 ;
32             //p和q的前k个字符相同,符合要求
33             if(i==k)
34                 //可能有n个q的前k个字符都和p相同,随机取一个
35                 if(rand()%(++qsofar)==0)
36                     nextp=q;
37         }
38         //c可能会是我们要输出的那一个字符
39         c=*(nextp+k);
40         if(c=='\0')
41             break;
42         putchar(c);
43         //改变p的值
44         p=nextp+1;
45     }
46 
47     return 0;
48 }

转载于:https://www.cnblogs.com/daniagger/archive/2012/05/05/2484551.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值