出处:https://blog.csdn.net/mobius_strip/article/details/27053639
题目链接:https://vjudge.net/contest/231030#problem/O
题目:给你一个数字串,判断他是哪一个Fib数的前缀,有多种答案输出最小的,不存在输出-1。
分析:字符串,大整数。
首先,利用大整数计算Fib的前100000项,由于数据较大,只储存前50位即可。
然后,按Fib的顺序存入字典树,利用滚动数组一边生成一边存储,可以减少内存开销。
在存的过程中直接进行标记,每个新节点直接标记成新加入的编号即标记路径。
这个值就表示到这个点结束的最小编号,这显然成立。
如果有更小的编号,应该更早早插入;而后面相同前缀的编号一定更大。
最后,读入字符换,查询即可,无论是否是单词节点,直接返回记录的编号即可。
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
using namespace std;
/* Trie define */
#define nodesize 4000004 //节点个数
#define dictsize 10 //字符集大小
typedef struct node1
{
int id;
int flag; //值域
node1* next[dictsize];
}tnode;
tnode dict[nodesize];
int ID[256];
class Trie
{
private:
int size;
tnode* root;
public:
Trie() {makeID(); initial();}
void makeID() {
for ( int i = 0 ; i < 10 ; ++ i )
ID['0'+i] = i;
}
void initial() {
memset( dict, 0, sizeof( dict ) );
root=NULL; size=0; root=newnode();
}
tnode* newnode() {return &dict[size ++];}
void insert( char* word, int L, int id ) {
tnode* now = root;
for ( int i = 0 ; i < L ; ++ i ) {
if ( !now->next[ID[word[i]]] )
now->next[ID[word[i]]] = newnode();
/* 标记路径 */
if ( !now->id && !now->flag ) now->id = id;
now = now->next[ID[word[i]]];
}
if ( !now->flag ) {
now->flag = 1;
now->id = id;
}
}
int query( char* word ) {
tnode* now = root;
for ( int i = 0 ; word[i] ; ++ i ) {
if ( !now->next[ID[word[i]]] ) return -1;
now = now->next[ID[word[i]]];
}
return now->id;
}
}trie;
/* Trie end */
int F[2][21000];
char FF[42],In[42];
int main()
{
/* 大整数计算Fib前100000个数字 */
memset( F, 0, sizeof(F) );
F[0][0] = F[1][0] = 1;
trie.insert( "1", 1, 0 );
int s = 0,l = 1,r,count,p,q;
for ( int i = 2 ; i < 100000 ; ++ i ) {
p = i%2, q = (i+1)%2;
for ( int j = s ; j < l ; ++ j )
F[p][j] = F[p][j] + F[q][j];
for ( int j = s ; j < l ; ++ j )
if ( F[p][j] >= 10 ) {
F[p][j+1] += 1;
F[p][j] -= 10;
}
if ( F[p][l] ) l ++;
if ( l - s > 50 ) s ++;
r = l-1; count = 0;
while ( r >= 0 && count < 40 )
FF[count ++] = F[p][r --] + '0';
trie.insert( FF, count, i );
}
int T;
while ( scanf("%d",&T) != EOF )
for ( int t = 1 ; t <= T ; ++ t ) {
scanf("%s",In);
printf("Case #%d: %d\n",t,trie.query( In ));
}
return 0;
}