回文树模板

const int MAXN = 210005 ;
const int N = 26 ;

struct Palindromic_Tree {
    int next[MAXN][N] ;//next指针,next指针和字典树类似,指向的串为当前串两端加上同一个字符构成
    int fail[MAXN] ;//fail指针,失配后跳转到fail指针指向的节点
    long long cnt[MAXN] ;
    //cnt[i]表示节点i表示的本质不同的串的个数(建树时求出的不是完全的,最后count()函数跑一遍以后才是正确的)
    int num[MAXN] ; //num[i]表示以节点i表示的最长回文串的最右端点为回文串结尾的回文串个数
    int len[MAXN] ;//len[i]表示节点i表示的回文串的长度
    int S[MAXN] ;//存放添加的字符
    int last ;//指向上一个字符所在的节点,方便下一次add
    int n ;//字符数组指针
    int p ;//节点指针

    int newnode ( int l ) {//新建节点
        for ( int i = 0 ; i < N ; ++ i ) next[p][i] = 0 ;
        cnt[p] = 0 ;
        num[p] = 0 ;
        len[p] = l ;
        return p ++ ;
    }

    void init () {//初始化
        p = 0 ;
        newnode (0) ;
        newnode (-1) ;
        last = 0 ;
        n = 0 ;
        S[n] = -1 ;//开头放一个字符集中没有的字符,减少特判
        fail[0] = 1 ;
    }

    int get_fail ( int x ) {//和KMP一样,失配后找一个尽量最长的
        while ( S[n - len[x] - 1] != S[n] ) x = fail[x] ;
        return x ;
    }

    void add ( int c ) {
        c -= 'a' ;
        S[++ n] = c ;
    //  cout<<n<<" "<<(char)(S[n]+'a')<<endl;
        int cur = get_fail ( last ) ;//通过上一个回文串找这个回文串的匹配位置
        if ( !next[cur][c] ) {//如果这个回文串没有出现过,说明出现了一个新的本质不同的回文串
            int now = newnode ( len[cur] + 2 ) ;//新建节点
            fail[now] = next[get_fail ( fail[cur] )][c] ;//和AC自动机一样建立fail指针,以便失配后跳转
            next[cur][c] = now ;
            num[now] = num[fail[now]] + 1 ;
        }
        last = next[cur][c] ;
        cnt[last] ++ ;
    }

    void count () {
        for ( int i = p - 1 ; i >= 0 ; -- i ) cnt[fail[i]] += cnt[i] ;
        //父亲累加儿子的cnt,因为如果fail[v]=u,则u一定是v的子回文串!
    }
} ;
Palindromic_Tree a1,b1;
long long ans;
char a[201312],b[223123];
void dfs(int x,int y)
{
    for(int i=0;i<N;i++)
    {
        int x1 =a1.next[x][i];
        int y1 =b1.next[y][i];
        if(x1&&y1)
        {
            ans+=(long long)(a1.cnt[x1]*b1.cnt[y1]);
            dfs(x1,y1);
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好,我理解了您的问题,以下是我的回答: 1. 编写非递归遍历算法,实现:给定一棵二叉的先序遍历序列和中序遍历序列,创建这棵。 可以使用栈来实现非递归遍历。具体实现如下: ```c #include <stdio.h> #include <stdlib.h> #define MAXSIZE 100 typedef struct TreeNode { char data; struct TreeNode *left; struct TreeNode *right; } TreeNode; typedef struct Stack { int top; TreeNode *data[MAXSIZE]; } Stack; void initStack(Stack *stack) { stack->top = -1; } int isEmpty(Stack *stack) { return stack->top == -1; } int isFull(Stack *stack) { return stack->top == MAXSIZE - 1; } void push(Stack *stack, TreeNode *node) { if (isFull(stack)) { return; } stack->top++; stack->data[stack->top] = node; } TreeNode* pop(Stack *stack) { if (isEmpty(stack)) { return NULL; } TreeNode *node = stack->data[stack->top]; stack->top--; return node; } TreeNode* createTree(char *preOrder, char *inOrder, int length) { if (preOrder == NULL || inOrder == NULL || length <= 0) { return NULL; } TreeNode *root = (TreeNode *) malloc(sizeof(TreeNode)); root->data = *preOrder; root->left = NULL; root->right = NULL; int rootIndex = 0; for (int i = 0; i < length; i++) { if (*(inOrder + i) == *preOrder) { rootIndex = i; break; } } root->left = createTree(preOrder + 1, inOrder, rootIndex); root->right = createTree(preOrder + rootIndex + 1, inOrder + rootIndex + 1, length - rootIndex - 1); return root; } void nonRecursivePreOrder(TreeNode *root) { if (root == NULL) { return; } Stack stack; initStack(&stack); TreeNode *node = root; while (node != NULL || !isEmpty(&stack)) { while (node != NULL) { printf("%c ", node->data); push(&stack, node); node = node->left; } if (!isEmpty(&stack)) { node = pop(&stack)->right; } } } void nonRecursiveInOrder(TreeNode *root) { if (root == NULL) { return; } Stack stack; initStack(&stack); TreeNode *node = root; while (node != NULL || !isEmpty(&stack)) { while (node != NULL) { push(&stack, node); node = node->left; } if (!isEmpty(&stack)) { node = pop(&stack); printf("%c ", node->data); node = node->right; } } } void nonRecursivePostOrder(TreeNode *root) { if (root == NULL) { return; } Stack stack1, stack2; initStack(&stack1); initStack(&stack2); TreeNode *node = root; push(&stack1, node); while (!isEmpty(&stack1)) { node = pop(&stack1); push(&stack2, node); if (node->left != NULL) { push(&stack1, node->left); } if (node->right != NULL) { push(&stack1, node->right); } } while (!isEmpty(&stack2)) { node = pop(&stack2); printf("%c ", node->data); } } void printLeaves(TreeNode *root) { if (root == NULL) { return; } if (root->left == NULL && root->right == NULL) { printf("%c ", root->data); } printLeaves(root->left); printLeaves(root->right); } int countNodes(TreeNode *root) { if (root == NULL) { return 0; } return 1 + countNodes(root->left) + countNodes(root->right); } int maxDepth(TreeNode *root) { if (root == NULL) { return 0; } int leftDepth = maxDepth(root->left) + 1; int rightDepth = maxDepth(root->right) + 1; return leftDepth > rightDepth ? leftDepth : rightDepth; } int main() { char *preOrder = "ABDECFG"; char *inOrder = "DBEAFCG"; TreeNode *root = createTree(preOrder, inOrder, 7); printf("前序遍历结果:"); nonRecursivePreOrder(root); printf("\n"); printf("中序遍历结果:"); nonRecursiveInOrder(root); printf("\n"); printf("后序遍历结果:"); nonRecursivePostOrder(root); printf("\n"); printf("叶子节点结果:"); printLeaves(root); printf("\n"); printf("结点个数结果:%d\n", countNodes(root)); printf("深度结果:%d\n", maxDepth(root)); return 0; } ``` 2. 输出二叉的后序遍历的结点序列。 可以使用两个栈来实现。具体实现如上面所示的代码中的 `nonRecursivePostOrder` 函数。 3. 输出二叉的叶子结点。 可以使用递归来实现。具体实现如上面所示的代码中的 `printLeaves` 函数。 4. 统计二叉的结点个数。用C语言实现。 可以使用递归来实现。具体实现如上面所示的代码中的 `countNodes` 函数。 5. 求二叉的深度。 可以使用递归来实现。具体实现如上面所示的代码中的 `maxDepth` 函数。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值