压缩是一种有效的减小数据量的方法,目前已经被广泛应用于各种类型的信息系统之中。一种压缩文本的方法如下:
原始文本文件中的非字母的字符,直接拷贝到压缩文件中;
原始文件中的词(全部由字母组成),如果是第一次出现,则将该词加入到一个词的列表中,并拷贝到压缩文件中;否则该词不拷贝到压缩文件中,而是将该词在词的列表中的位置拷贝到压缩文件中;
词的列表的起始位置为 1。
词的定义为文本中由大小写字母组成的最大连续序列。(单词不跨行)大写字母和小写字母认为是不同的字母,即 abc 和 Abc 是不同的词。例子如下:
x-ray 包括两个词 x 和 ray
mary’s 包括两个词 mary 和 s
a c-Dec 包括三个词 a 和 c 和 Dec
请编写一个程序,实现文本的压缩。
输入
输入为一段文本,你可以假设输入中不会出现数字,词的数量不会超过 1’000’000,并且输入文本的大小不超过 10M。
输出
输出压缩后的文本。
测试用例
in:
Please, please do it–it would please Mary very,
very much.
Thanks
out:
Please, please do it–4 would 2 Mary very,
7 much.
Thanks
大一做过这题,然而数据量没那么变态,直接把单词存在二维数组并在前面标号。如果新的单词和之前表里面的单词重复则输出标号,否则原样输出。然而这样会re,因为我们开不了那么大的数组,后面经大佬的指点,自学了hash表拉链法解决冲突才过的。
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<ctype.h>
#define MAX 60013
const int mod1=60013;
const int mult1=1013;
const long mod2=1000000007;
const long mult2=1000007;
typedef struct node
{
int val1;
int val2;
struct node *next;
}HashTable;
char ch,s[100];
int repeat;
int flag,k;
HashTable *Hash[MAX],*vis;
int FirstHash(char s[]);
int SecondHash(char s[]);
void insert(HashTable **Hash,int repeat,char s[]);
int find(HashTable **Hash,int repeat[],char s[]);
int main()
{
int j=1;
for(int i=0;i<mod1;i++)
Hash[i]=NULL;
while(~(ch=getchar()))
{
if(!isalpha(ch))
{
if(!flag)
{
s[k]='\0';
repeat=0;
if(find(Hash,&repeat,s))
printf("%d",repeat);
else
{
insert(Hash,j++,s);
printf("%s",s);
}
putchar(ch);
flag=1;
k=0;
}
else
{
putchar(ch);
flag=1;
}
}
else
{
flag=0;
s[k++]=ch;
}
}
}
int FirstHash(char s[])
{
int ans=0;
for(int i=0;i<strlen(s);i++)
ans=(ans*mult1+s[i]-'A'+1)%mod1;
return ans;
}
int SecondHash(char s[])
{
int ans=0;
for(int i=0;i<strlen(s);i++)
ans=(ans*mult2+s[i]-'A'+1)%mod2;
return ans;
}
void insert(HashTable **Hash,int repeat,char s[])
{
int key=FirstHash(s);
HashTable *q=(HashTable*)malloc(sizeof(HashTable));
q->val1=repeat;
q->next=NULL;
q->val2=SecondHash(s);
if(Hash[key]!=NULL)
vis->next=q;
else
Hash[key]=q;
}
int find(HashTable **Hash,int repeat[],char s[])
{
int key2=FirstHash(s);
HashTable *p=Hash[key2];
int val2=SecondHash(s);
if(p==NULL)
return 0;
while(p->next!=NULL)
{
if(p->val2==val2)
{
*repeat=p->val1;
return 1;
}
p=p->next;
}
if(p->val2==val2)
{
*repeat=p->val1;
return 1;
}
vis=p;
return 0;
}