#include <iostream>
#include <vector>
#include <unordered_map>
#include <bitset>

constexpr int64_t p = 998244353;
typedef std::vector<int64_t> flagmap;

bool isflag(int a, int b, int c, int d)
{
    return a == 0 && b == 1 && c ==2 && d == 1;
}

void populateNoFlags(const std::vector<uint64_t> &grid, flagmap *fm, int cur, int m, uint64_t hash)
{
    if(cur == m)
    {
        fm[0][hash] = 1;
        return;
    }

    if(grid[cur] == 3)
    {
        for(uint64_t j=0; j<3; j++)
        {   
            uint64_t newhash = hash;
            newhash |= (j << (2*cur));
            populateNoFlags(grid, fm, cur+1, m, newhash);
        }
    }
    else
    {
        hash |= (grid[cur] << (2*cur));
        populateNoFlags(grid, fm, cur+1, m, hash);
    }
}

bool validHash(uint64_t hash, int m)
{
    for(int i=0; i<m; i++)
    {
        if( ((hash >> (2*i)) & 3ULL) == 3ULL)
            return false;
    }
    return true;
}

int main()
{
    int n, m;
    std::cin >> n >> m;
    std::vector<uint64_t> grid(n*m);
    for(int i=0; i<n*m; i++)
    {
        char c;
        std::cin >> c;
        if(c == 'I')
            grid[i] = 0;
        else if(c == 'C')
            grid[i] = 1;
        else if(c == 'P')
            grid[i] = 2;        
        else
            grid[i] = 3;
    }
    
    int64_t mapsize = (1LL << (2*m));
    
    flagmap noflags[3];
    flagmap flags[3];
    for(int i=0; i<3; i++)
    {
        noflags[i].resize(mapsize);
        flags[i].resize(mapsize);
    }
    
    populateNoFlags(grid, noflags, 0, m, 0);
    
    for(int row=1; row<n; row++)
    {
        {
            flagmap newnoflags[3];
            flagmap newflags[3];
            for(int i=0; i<3; i++)
            {
                newnoflags[i].resize(mapsize);
                newflags[i].resize(mapsize);
            }

            for(int prev=0; prev<3; prev++)
            {
                for(int hash = 0; hash < mapsize; hash++)
                {
                    if(!validHash(hash, m))
                        continue;
                    uint64_t newhash = hash;
                    newhash &= ~(3ULL);
                    std::vector<uint64_t> toprocess;
                    if(grid[row*m] == 3)
                        toprocess = {0ULL, 1ULL, 2ULL};
                    else toprocess.push_back(grid[row*m]);
                    for(uint64_t j : toprocess)
                    {
                        newnoflags[hash & 3][newhash | j] = (newnoflags[hash & 3][newhash | j] + noflags[prev][hash]) % p;
                        newflags[hash & 3][newhash | j] = (newflags[hash & 3][newhash | j] + flags[prev][hash]) % p;
                    }
                }
            }
            for(int i=0; i<3; i++)
            {
                noflags[i] = newnoflags[i];
                flags[i] = newflags[i];
            }
        }
        for(int col = 1; col < m; col++)
        {
            flagmap newnoflags[3];
            flagmap newflags[3];
            for(int i=0; i<3; i++)
            {
                newnoflags[i].resize(mapsize);
                newflags[i].resize(mapsize);
            }

            for(int prev=0; prev<3; prev++)
            {
                for(int64_t hash = 0; hash < mapsize; hash++)
                {
                    if(!validHash(hash, m))
                        continue;

                    uint64_t newhash = hash;
                    newhash &= ~(3ULL << (2*col));
                    std::vector<uint64_t> toprocess;
                    if(grid[row*m + col] == 3)
                        toprocess = {0ULL, 1ULL, 2ULL};
                    else
                        toprocess.push_back(grid[row*m + col]);
                    for(uint64_t j : toprocess)
                    {            
                        if(isflag(prev, (hash >> (2*col)) & 3ULL, (hash >> (2*(col-1))) & 3ULL, j))
                            newflags[(hash >> (2*col)) & 3ULL][newhash | (j << (2*col))] = (newflags[(hash >> (2*col)) & 3ULL][newhash | (j << (2*col))] + noflags[prev][hash]) % p;
                        else
                        {
                            newnoflags[(hash >> (2*col)) & 3ULL][newhash | (j << (2*col))] = (newnoflags[(hash >> (2*col)) & 3ULL][newhash | (j << (2*col))] + noflags[prev][hash]) % p;
                        }
                        newflags[(hash >> (2*col)) & 3ULL][newhash | (j << (2*col))] = (newflags[(hash >> (2*col)) & 3ULL][newhash | (j << (2*col))] + flags[prev][hash]) % p;
                    }
                }
            }
            for(int i=0; i<3; i++)
            {
                noflags[i] = newnoflags[i];
                flags[i] = newflags[i];            
            }
        }
    }
    
    uint64_t finalanswer = 0;
    for(int j=0; j<3; j++)
    {
        for(int64_t hash = 0; hash < mapsize; hash++)
        {
            finalanswer = (finalanswer + flags[j][hash]) % p;
        }
    }
    
    std::cout << finalanswer << std::endl;
}
